package service

import (
	"encoding/json"
	"fmt"
	ClickHouse "gin/database"
	"gin/model"
	"gin/types"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"strconv"
	"strings"
	"time"
)

type ProductionManage struct {
}

// 剧集
type EpisodeInfo struct {
	Id            uint64 `json:"id"`
	Name          string `json:"name"`            // 剧集名称
	Deliver       string `json:"deliver"`         // 交付时间
	Play          string `json:"play"`            // 播出时间
	EpisodeIsSeal string `json:"episode_is_seal"` // 是否封板
}

// 任务统计字段
type TaskStatistics struct {
	Total    uint64  `json:"total"`
	MakeIng  uint64  `json:"make_ing"`
	Overdue  uint64  `json:"overdue"`
	Schedule float64 `json:"schedule"` // 进度
}

type ProductionManageItem struct {
	RepairIng          uint64         `json:"repair_ing"`
	TotalRepair        uint64         `json:"total_repair"`
	LinkPlanEndTime    uint64         `json:"link_plan_end_time"`
	NotClosedWorkOrder uint64         `json:"not_closed_work_order"`
	TotalTask          TaskStatistics `json:"total_task"`
	FilterTask         TaskStatistics `json:"filter_task"`
}

// ListItem
type ListItem struct {
	Code               string         `json:"code"`
	RepairIng          uint64         `json:"repair_ing"`
	TotalRepair        uint64         `json:"total_repair"`
	LinkPlanEndTime    int64          `json:"link_plan_end_time"`
	NotClosedWorkOrder uint64         `json:"not_closed_work_order"`
	TotalTask          TaskStatistics `json:"total_task"`
	FilterTask         TaskStatistics `json:"filter_task"`
	StepCategoryId     int            `json:"step_category_id"`
	RepairRate         float64        `json:"repair_rate"`
	StepId             int            `json:"step_id"`
	IsStandard         string         `json:"is_standard"`
	StepName           string         `json:"step_name"`
	IsEnableCensus     string         `json:"is_enable_census"`
}
type CardInfoList map[string]interface{}

type ColumnItem struct {
	Name  string `json:"name"`
	Code  string `json:"code"`
	Index uint64 `json:"index"`
}

type ProductionManageRes struct {
	EpisodeInfo     EpisodeInfo  `json:"episode_info"`
	CardInfoList    interface{}  `json:"card_info_list"`
	Column          []ColumnItem `json:"column"`
	NotCensusColumn []ColumnItem `json:"not_census_column"`
}

var StatusList = func() (res map[string]uint64) {
	var statusList []struct {
		Id   uint64 `json:"id"`
		Name string `json:"name"`
		Code string `json:"code"`
	}
	var statusMap = make(map[string]uint64)
	ClickHouse.DB.Model(&model.Status{}).
		Find(&statusList)
	for _, v := range statusList {
		statusMap[v.Code] = v.Id
	}
	res = statusMap
	return
}

// QueryUserWorkHour 获取项目统计工序分类配置
func (P ProductionManage) GetStatisticalStepCategoryConfig(Req types.ProductionManageReq, ctx *gin.Context) (resList types.StatisticalStepCategoryConfig, err error) {
	var tr TeamonesRequest
	var req types.StatisticalStepCategoryConfigReq
	req.Param.Filter.ProjectId = Req.ProjectIdList[0]
	var headers = map[string]string{"x-userinfo": GetStringFromContext(ctx, "x-userinfo")}
	err = tr.Do("teamones-saas", "project/statistical_step_category_config", req, headers, &resList)
	if err != nil {
		return
	}
	return
}

// 获取环节逾期
func (P ProductionManage) GetLinkOverdueNum(Req types.ProductionManageReq, episodeId []uint64, tenantId int64, StepCategoryIds []int) (res map[string]types.OverDueNumRes, err error) {

	StatusLists := StatusList()
	var OverDueNumList []types.OverDueNumRes
	query := ClickHouse.DB.Model(&model.Task{}).
		Select("epr.episode_id as EpisodeId,count(distinct task.id) as OverdueNum,step_category_id as StepCategoryId").
		Joins("JOIN (select distinct entity_id, episode_id from entity_episode_relation  where episode_id in (?)) epr on task.entity_id = epr.entity_id", episodeId).
		Where("task.tenant_id = ? ", tenantId).
		Where("task.step_category_id IN (?)", StepCategoryIds).
		Where("JSONExtractString(task.json, 'task_is_overdue') = 'yes'").
		Where("simpleJSONExtractInt(task.json, 'task_status') != ?", StatusLists["final"]).
		Where("JSONLength(JSONExtractString(task.json, 'task_deprecate_data')) = 0 and simpleJSONExtractInt(task.json,'task_status') <> 3")

	if len(Req.ProjectIdList) > 0 {
		query.Where("task.project_id IN (?) ", Req.ProjectIdList)
	}
	if Req.StartTime > 0 && Req.EndTime > 0 {
		query.Where("task.plan_end_time between ? and ?", Req.StartTime, Req.EndTime)
	}
	query.Where("task.step_type = 'step_category'").Group("task.step_category_id,epr.episode_id")
	err = query.
		Find(&OverDueNumList).Error

	res = make(map[string]types.OverDueNumRes, len(OverDueNumList))
	for i, data := range OverDueNumList {
		k := fmt.Sprintf("%d-%d", data.EpisodeId, data.StepCategoryId)
		res[k] = OverDueNumList[i]
	}
	return
}

// 获取工序逾期
func (P ProductionManage) GetLinkStepOverdueNum(Req types.ProductionManageInfoReq, episodeId []uint64, tenantId int64) (res map[string]types.OverDueStepNumRes, err error) {

	StatusLists := StatusList()
	var OverDueStepNumList []types.OverDueStepNumRes
	query := ClickHouse.DB.Model(&model.EntityEpisodeRelation{}).
		Select("entity_episode_relation.episode_id as EpisodeId,count(distinct task.id) as OverdueNum,step_id as StepId").
		Joins("JOIN task on entity_episode_relation.entity_id = task.entity_id").
		Joins("JOIN (select distinct entity_id, episode_id from entity_episode_relation  where episode_id in (?)) epr on entity_episode_relation.entity_id = epr.entity_id", episodeId).
		Where("task.tenant_id = ? ", tenantId).
		Where("task.step_category_id IN (?)", Req.StepCategoryIdList).
		Where("JSONExtractString(task.json, 'task_is_overdue') = 'yes'").
		Where("simpleJSONExtractInt(task.json, 'task_status') != ?", StatusLists["final"]).
		Where("JSONLength(JSONExtractString(task.json, 'task_deprecate_data')) = 0 and simpleJSONExtractInt(task.json,'task_status') <> 3")
	if len(episodeId) > 0 {
		query.Where("entity_episode_relation.episode_id IN (?) ", episodeId)
	}
	if len(Req.ProjectIdList) > 0 {
		query.Where("task.project_id IN (?) ", Req.ProjectIdList)
	}
	if Req.StartTime > 0 && Req.EndTime > 0 {
		query.Where("task.plan_end_time between ? and ?", Req.StartTime, Req.EndTime)
	}
	query.Where("task.step_type = 'step'").Group("task.step_id,entity_episode_relation.episode_id")
	err = query.
		Find(&OverDueStepNumList).Error

	res = make(map[string]types.OverDueStepNumRes, len(OverDueStepNumList))
	for i, data := range OverDueStepNumList {
		k := fmt.Sprintf("%d-%d", data.EpisodeId, data.StepId)
		res[k] = OverDueStepNumList[i]
	}
	return
}

// GetEpisodeTaskData 获取剧集下的任务信息
func (P ProductionManage) GetEpisodeTaskData(Req types.ProductionManageInfoReq, episodeId []uint64, tenantId int64) (res map[string]types.StepEpisodeTask, err error) {

	var stepEpisodeTaskList []types.StepEpisodeTask
	query := ClickHouse.DB.Model(&model.Task{}).
		Select("count(task.id) as Num,task.step_id as StepId,epr.episode_id as EpisodeId").
		Joins("JOIN (select distinct entity_id, episode_id from entity_episode_relation  where episode_id in (?)) epr on task.entity_id = epr.entity_id", episodeId).
		Where("task.tenant_id = ? ", tenantId).
		Where("step_category_id IN (?)", Req.StepCategoryIdList)

	if len(Req.ProjectIdList) > 0 {
		query.Where("task.project_id IN (?) ", Req.ProjectIdList)
	}
	if Req.StartTime > 0 && Req.EndTime > 0 {
		query.Where("task.plan_end_time between ? and ?", Req.StartTime, Req.EndTime)
	}
	query.Where("task.step_type = 'step'")
	err = query.Group("task.step_id, epr.episode_id").
		Find(&stepEpisodeTaskList).Error

	res = make(map[string]types.StepEpisodeTask, len(stepEpisodeTaskList))
	for i, data := range stepEpisodeTaskList {
		k := fmt.Sprintf("%d-%d", data.EpisodeId, data.StepId)
		res[k] = stepEpisodeTaskList[i]
	}
	return
}

// 获取制中的数据
func (P ProductionManage) getMakingList(Req types.ProductionManageReq, episodeId []uint64, tenantId int64, StepCategoryIds []int) (res map[string]types.MakingList, err error) {

	StatusLists := StatusList()
	MakingStatusIds := []uint64{StatusLists["inprogress"], StatusLists["submitted"], StatusLists["feedback"],
		StatusLists["ready_to_publish"], StatusLists["wait_for_party_a_review"], StatusLists["remake"]}
	var makingList []types.MakingList
	query := ClickHouse.DB.Model(&model.Task{}).
		Select("epr.episode_id as EpisodeId,task.step_category_id as StepCategoryId,count(task.id) as MakingNum").
		Joins("JOIN (select distinct entity_id, episode_id from entity_episode_relation  where episode_id in (?)) epr on task.entity_id = epr.entity_id", episodeId).
		Where("task.tenant_id = ? ", tenantId).
		Where("simpleJSONExtractInt(task.json, 'task_status') IN (?)", MakingStatusIds).
		Where("step_category_id IN (?)", StepCategoryIds)

	if len(Req.ProjectIdList) > 0 {
		query.Where("task.project_id IN (?) ", Req.ProjectIdList)
	}
	if Req.StartTime > 0 && Req.EndTime > 0 {
		query.Where("task.plan_end_time between ? and ?", Req.StartTime, Req.EndTime)
	}
	query.Where("task.step_type = 'step_category'").Group("epr.episode_id,task.step_category_id")
	err = query.
		Find(&makingList).Error

	res = make(map[string]types.MakingList, len(makingList))
	for i, data := range makingList {
		k := fmt.Sprintf("%d-%d", data.EpisodeId, data.StepCategoryId)
		res[k] = makingList[i]
	}
	return
}

// 获取工序制作中的数据
func (P ProductionManage) getStepMakingList(Req types.ProductionManageInfoReq, episodeId []uint64, tenantId int64) (res map[string]types.StepMakingList, err error) {

	StatusLists := StatusList()
	MakingStatusIds := []uint64{StatusLists["inprogress"], StatusLists["submitted"], StatusLists["feedback"],
		StatusLists["ready_to_publish"], StatusLists["wait_for_party_a_review"], StatusLists["remake"]}

	var StepMakingList []types.StepMakingList
	query := ClickHouse.DB.Model(&model.EntityEpisodeRelation{}).
		Select("entity_episode_relation.episode_id as EpisodeId,task.step_id as StepId,count(distinct task.id) as MakingNum").
		Joins("JOIN entity on entity_episode_relation.entity_id = entity.id").
		Joins("JOIN task on entity.id = task.entity_id").
		Joins("JOIN (select distinct entity_id, episode_id from entity_episode_relation  where episode_id in (?)) epr on entity_episode_relation.entity_id = epr.entity_id", episodeId).
		Where("entity.tenant_id = ? ", tenantId).
		Where("simpleJSONExtractInt(task.json, 'task_status') IN (?)", MakingStatusIds).
		Where("step_category_id IN (?)", Req.StepCategoryIdList)
	if len(episodeId) > 0 {
		query.Where("entity_episode_relation.episode_id IN (?) ", episodeId)
	}
	if len(Req.ProjectIdList) > 0 {
		query.Where("entity.project_id IN (?) ", Req.ProjectIdList)
	}
	if Req.StartTime > 0 && Req.EndTime > 0 {
		query.Where("task.plan_end_time between ? and ?", Req.StartTime, Req.EndTime)
	}
	query.Where("task.step_type = 'step'").Group("entity_episode_relation.episode_id,task.step_id")
	err = query.
		Find(&StepMakingList).Error

	res = make(map[string]types.StepMakingList, len(StepMakingList))
	for i, data := range StepMakingList {
		k := fmt.Sprintf("%d-%d", data.EpisodeId, data.StepId)
		res[k] = StepMakingList[i]
	}
	return
}

//// 查询工序返修率列表
//func (P ProductionManage) getUnderRepairStepData(Req types.ProductionManageInfoReq, episodeId []uint64, tenantId uint64) (res map[string]types.StepUnderRepair, err error) {
//
//	var StepUnderRepairList []types.StepUnderRepair
//
//	ClickHouse.DB.Raw("SELECT sum(a.maxNumber) AS MaxNumber, a.episode_id AS EpisodeId, a.step_id AS StepId ,"+
//		" count(a.id) AS Num FROM ( SELECT max(v.number) AS maxNumber, epr.episode_id AS episode_id, t.step_id AS step_id,"+
//		" epr.entity_id AS id FROM ( SELECT DISTINCT entity_id, episode_id FROM entity_episode_relation"+
//		" WHERE episode_id IN (?) ) epr JOIN task t ON epr.entity_id = t.entity_id"+
//		" JOIN version v ON v.link_id = t.id WHERE t.project_id IN (?) AND t.tenant_id = ? GROUP BY epr.episode_id, t.step_id, epr.entity_id ) a"+
//		" GROUP BY a.episode_id, a.step_id", episodeId, Req.ProjectIdList, tenantId).
//		Scan(&StepUnderRepairList)
//
//	res = make(map[string]types.StepUnderRepair, len(StepUnderRepairList))
//	for i, data := range StepUnderRepairList {
//		k := fmt.Sprintf("%d-%d", data.EpisodeId, data.StepId)
//		res[k] = StepUnderRepairList[i]
//	}
//	return
//}

// GetEpisodeJsonList 查询集的json信息
func (P ProductionManage) GetEpisodeJsonList(episodeId []uint64) (res map[uint64]types.EpisodeJson, err error) {

	var EpisodeList []types.EpisodeJson
	query := ClickHouse.DB.Model(&model.Entity{}).
		Select("id,name,JSONExtractString(entity.json, 'episode_plan_seal_time') as episode_plan_seal_time," +
			"JSONExtractString(entity.json,'episode_plan_show_time') as episode_plan_show_time,JSONExtractString(entity.json, 'episode_is_seal') as episode_is_seal")
	if len(episodeId) > 0 {
		query.Where("id IN (?) ", episodeId)
	}
	err = query.
		Find(&EpisodeList).Error

	res = make(map[uint64]types.EpisodeJson, len(EpisodeList))
	for i, data := range EpisodeList {
		res[data.Id] = EpisodeList[i]
	}
	return
}

// GetRepairStepCategoryList 查询工序返修中
func (P ProductionManage) GetStepRepairIngList(Req types.ProductionManageInfoReq, episodeId []uint64, tenantId int64) (res map[string]types.StepRepairIng, err error) {

	var StepCategoryRepairIngList []types.StepRepairIng
	query := ClickHouse.DB.Model(&model.Task{}).
		Select("epr.episode_id as episode_id,count(distinct task.id) as repair_ing_num, task.step_id as step_id").
		Joins("JOIN (select distinct entity_id, episode_id from entity_episode_relation  where episode_id in (?)) epr on task.entity_id = epr.entity_id", episodeId).
		Joins("JOIN repair_order_affected_task roat on task.id = roat.task_id").
		Where("task.tenant_id = ? ", tenantId).
		Where("step_category_id IN (?)", Req.StepCategoryIdList)
	if len(Req.ProjectIdList) > 0 {
		query.Where("task.project_id IN (?) ", Req.ProjectIdList)
	}
	query.Where("roat.repair_status = 'no'")
	query.Where("task.step_type = 'step'")
	err = query.Group("task.step_id,epr.episode_id").
		Find(&StepCategoryRepairIngList).Error

	res = make(map[string]types.StepRepairIng, len(StepCategoryRepairIngList))
	for i, data := range StepCategoryRepairIngList {
		k := fmt.Sprintf("%d-%d", data.EpisodeId, data.StepId)
		res[k] = StepCategoryRepairIngList[i]
	}
	return
}

// GetRepairStepCategoryList 查询工序返修数
func (P ProductionManage) GetStepRepairList(Req types.ProductionManageInfoReq, episodeId []uint64, tenantId int64) (res map[string]types.StepRepair, err error) {

	var StepCategoryRepairList []types.StepRepair
	query := ClickHouse.DB.Model(&model.Task{}).
		Select("epr.episode_id as EpisodeId,count(distinct task.id) as RepairNum, task.step_id as StepId").
		Joins("JOIN (select distinct entity_id,episode_id from entity_episode_relation where episode_id in (?)) epr on task.entity_id = epr.entity_id", episodeId).
		Joins("JOIN repair_order_affected_task roat on task.id = roat.task_id").
		Where("task.tenant_id = ? ", tenantId).
		Where("step_category_id IN (?)", Req.StepCategoryIdList)
	if len(Req.ProjectIdList) > 0 {
		query.Where("task.project_id IN (?) ", Req.ProjectIdList)
	}
	query.Where("task.step_type = 'step'")
	err = query.Group("task.step_id,epr.episode_id").
		Find(&StepCategoryRepairList).Error

	res = make(map[string]types.StepRepair, len(StepCategoryRepairList))
	for i, data := range StepCategoryRepairList {
		k := fmt.Sprintf("%d-%d", data.EpisodeId, data.StepId)
		res[k] = StepCategoryRepairList[i]
	}
	return
}

// GetRepairStepCategoryList 查询环节返修中
func (P ProductionManage) GetStepCategoryRepairIngList(Req types.ProductionManageReq, episodeId []uint64, tenantId int64, StepCategoryIds []int) (res map[string]types.StepCategoryRepairIng, err error) {

	var StepCategoryRepairIngList []types.StepCategoryRepairIng
	query := ClickHouse.DB.Model(&model.Task{}).
		Select("epr.episode_id as EpisodeId,count(distinct task.id) as RepairIngNum, task.step_category_id as StepCategoryId").
		Joins("JOIN (select distinct entity_id, episode_id from entity_episode_relation  where episode_id in (?)) epr on task.entity_id = epr.entity_id", episodeId).
		Joins("JOIN repair_order_affected_task roat on task.id = roat.task_id").
		Where("task.tenant_id = ? ", tenantId).
		Where("step_category_id IN (?)", StepCategoryIds)
	if len(Req.ProjectIdList) > 0 {
		query.Where("task.project_id IN (?) ", Req.ProjectIdList)
	}
	query.Where("roat.repair_status = 'no'")
	err = query.Group("task.step_category_id,epr.episode_id").
		Find(&StepCategoryRepairIngList).Error

	res = make(map[string]types.StepCategoryRepairIng, len(StepCategoryRepairIngList))
	for i, data := range StepCategoryRepairIngList {
		k := fmt.Sprintf("%d-%d", data.EpisodeId, data.StepCategoryId)
		res[k] = StepCategoryRepairIngList[i]
	}
	return
}

// GetStepCategoryRepairNumList 查询环节返修数
func (P ProductionManage) GetStepCategoryRepairNumList(Req types.ProductionManageReq, episodeId []uint64, tenantId int64, StepCategoryIds []int) (res map[string]types.StepCategoryRepairNum, err error) {

	var StepCategoryRepairIngList []types.StepCategoryRepairNum
	query := ClickHouse.DB.Model(&model.Task{}).
		Select("epr.episode_id as EpisodeId,count(distinct task.id) as RepairNum, task.step_category_id as StepCategoryId").
		Joins("JOIN (select distinct entity_id, episode_id from entity_episode_relation where episode_id in (?)) epr on task.entity_id = epr.entity_id", episodeId).
		Joins("JOIN repair_order_affected_task roat on task.id = roat.task_id").
		Where("task.tenant_id = ? ", tenantId).
		Where("step_category_id IN (?)", StepCategoryIds)
	if len(Req.ProjectIdList) > 0 {
		query.Where("task.project_id IN (?) ", Req.ProjectIdList)
	}
	query.Where("task.step_type = 'step_category'")
	err = query.Group("task.step_category_id,epr.episode_id").
		Find(&StepCategoryRepairIngList).Error

	res = make(map[string]types.StepCategoryRepairNum, len(StepCategoryRepairIngList))
	for i, data := range StepCategoryRepairIngList {
		k := fmt.Sprintf("%d-%d", data.EpisodeId, data.StepCategoryId)
		res[k] = StepCategoryRepairIngList[i]
	}
	return
}

// GetRepairStepCategoryList 查询环节返修率
//func (P ProductionManage) GetRepairStepCategoryList(projectIdList []uint64, episodeId []uint64, tenantId uint64) (res map[string]types.RepairStepCategory, err error) {
//
//	var RepairStepCategoryList []types.RepairStepCategory
//	ClickHouse.DB.Raw("SELECT sum(a.maxNumber) AS MaxNumber, a.episode_id AS EpisodeId, a.step_category_id AS StepCategoryId ,"+
//		" count(a.id) AS Num FROM ( SELECT max(v.number) AS maxNumber, epr.episode_id AS episode_id, t.step_category_id AS step_category_id,"+
//		" epr.entity_id AS id FROM ( SELECT DISTINCT entity_id, episode_id FROM entity_episode_relation WHERE episode_id IN (?) ) epr"+
//		" JOIN task t ON epr.entity_id = t.entity_id JOIN version v ON v.link_id = t.id WHERE t.project_id IN (?) AND t.tenant_id = ?"+
//		" GROUP BY epr.episode_id, t.step_category_id, epr.entity_id ) a"+
//		" GROUP BY a.episode_id, a.step_category_id", episodeId, projectIdList, tenantId).
//		Scan(&RepairStepCategoryList)
//	res = make(map[string]types.RepairStepCategory, len(RepairStepCategoryList))
//	for i, data := range RepairStepCategoryList {
//		k := fmt.Sprintf("%d-%d", data.EpisodeId, data.StepCategoryId)
//		res[k] = RepairStepCategoryList[i]
//	}
//	return
//}

// GetStepFinishTaskData 查询工序未完成任务
func (P ProductionManage) GetStepFinishTaskData(Req types.ProductionManageInfoReq, episodeId []uint64, tenantId int64) (res map[string]types.StepFinishTask, err error) {

	var status []struct {
		Id   uint64 `json:"id"`
		Code string `json:"code"`
	}
	err = ClickHouse.DB.Model(&model.Status{}).Find(&status).Error
	if err != nil {
		return
	}
	statusList := make(map[string]uint64, 0)
	for _, s := range status {
		statusList[s.Code] = s.Id
	}
	var StepCategoryFinishTaskList []types.StepFinishTask
	query := ClickHouse.DB.Model(&model.Task{}).
		Select("count(task.id) as Num,task.step_id as StepId,epr.episode_id as EpisodeId").
		Joins("JOIN (select distinct entity_id, episode_id from entity_episode_relation  where episode_id in (?)) epr on task.entity_id = epr.entity_id", episodeId).
		Where("task.tenant_id = ? ", tenantId).
		Where("step_category_id IN (?)", Req.StepCategoryIdList).
		Where("simpleJSONExtractUInt(task.json, 'task_status') = ?", statusList["final"])
	if len(Req.ProjectIdList) > 0 {
		query.Where("task.project_id IN (?) ", Req.ProjectIdList)
	}
	query.Where("task.step_type = 'step'")
	err = query.Group("task.step_id,epr.episode_id").
		Find(&StepCategoryFinishTaskList).Error

	res = make(map[string]types.StepFinishTask, len(StepCategoryFinishTaskList))
	for i, data := range StepCategoryFinishTaskList {
		k := fmt.Sprintf("%d-%d", data.EpisodeId, data.StepId)
		res[k] = StepCategoryFinishTaskList[i]
	}
	return
}

// GetStepCategoryFinishTaskData 查询环节已完成任务
func (P ProductionManage) GetStepCategoryFinishTaskData(Req types.ProductionManageReq, episodeId []uint64, tenantId int64, StepCategoryIds []int) (res map[string]types.StepCategoryFinishTask, err error) {

	var StepCategoryFinishTaskList []types.StepCategoryFinishTask
	StatusLists := StatusList()
	query := ClickHouse.DB.Model(&model.Task{}).
		Select("count(task.id) as Num,task.step_category_id as StepCategoryId,epr.episode_id as EpisodeId").
		Joins("JOIN (select distinct entity_id, episode_id from entity_episode_relation  where episode_id in ?) epr on task.entity_id = epr.entity_id", episodeId).
		Where("task.tenant_id = ? ", tenantId).
		Where("step_category_id IN (?)", StepCategoryIds).
		Where("simpleJSONExtractUInt(task.json, 'task_status') = ?", StatusLists["final"])
	if len(Req.ProjectIdList) > 0 {
		query.Where("task.project_id IN (?) ", Req.ProjectIdList)
	}
	if Req.StartTime > 0 && Req.EndTime > 0 {
		query.Where("task.plan_end_time between ? and ?", Req.StartTime, Req.EndTime)
	}
	query.Where("task.step_type = 'step_category'")
	err = query.Group("task.step_category_id,epr.episode_id").
		Find(&StepCategoryFinishTaskList).Error

	res = make(map[string]types.StepCategoryFinishTask, len(StepCategoryFinishTaskList))
	for i, data := range StepCategoryFinishTaskList {
		k := fmt.Sprintf("%d-%d", data.EpisodeId, data.StepCategoryId)
		res[k] = StepCategoryFinishTaskList[i]
	}
	return
}

// List 制片管理列表
func (P ProductionManage) List(Req types.ProductionManageReq, tenantId int64, page []int, ctx *gin.Context) (res []interface{}, err error) {

	// 获取项目统计工序分类配置
	StatisticalStepCategoryConfigList, _ := P.GetStatisticalStepCategoryConfig(Req, ctx)
	var StepTaskData []types.StepTaskInfoRes
	var StepCategoryIdList []int

	// 处理工序分类Column
	var StepCategoryIds []int
	for _, v := range StatisticalStepCategoryConfigList.Data {
		if v.IsShow == "no" {
			continue
		}
		StepTaskData = append(StepTaskData, types.StepTaskInfoRes{
			StepCategoryId: v.Id,
			EpisodeId:      0,
			StepId:         0,
			Num:            0,
			StepCode:       v.Code,
			IsStandard:     v.IsStandard,
			IsEnableCensus: v.IsEnableCensus,
			StepName:       v.Name,
			ShowName:       v.ShowName,
			ShowIndex:      v.ShowIndex,
		})
		StepCategoryIdList = append(StepCategoryIdList, v.Id)
		StepCategoryIds = append(StepCategoryIds, v.Id)
	}
	if len(StepCategoryIds) <= 0 {
		return
	}
	var moduleInfo struct {
		Id   uint64 `json:"id"`
		Code string `json:"code"`
	}
	// 剧集
	ClickHouse.DB.Model(&model.Module{}).Select("id,code").Where("code='episode'").First(&moduleInfo)

	where := ClickHouse.DB.Where("entity.tenant_id = ? ", tenantId).
		Where("entity.module_id = ?", moduleInfo.Id)
	if len(Req.ProjectIdList) > 0 {
		where.Where("entity.project_id IN (?)", Req.ProjectIdList)
	}
	if len(Req.Episode) > 0 {
		where.Where("entity.name IN (?)", Req.Episode)
	}
	// 获取剧集列表
	episodeData, episodeErr := P.GetEpisodeRelationStepList(where, page[0], page[1])
	if episodeErr != nil {
		err = episodeErr
	}

	// 组织剧集id
	var episodeId []uint64
	for _, episodeItem := range episodeData {
		episodeId = append(episodeId, episodeItem.EpisodeId)
	}
	if len(episodeId) <= 0 {
		return
	}

	// 总计-区间时间段
	EpisodeTaskData, EpisodeTaskErr := P.GetEpisodeTaskList(Req, episodeId, tenantId, StepCategoryIds)

	if EpisodeTaskErr != nil {
		err = EpisodeTaskErr
	}
	// 制作任务-区间时间段
	makingData, makingListErr := P.getMakingList(Req, episodeId, tenantId, StepCategoryIds)
	if makingListErr != nil {
		err = makingListErr
	}
	// 逾期任务-区间时间段
	OverdueNumData, OverdueNumErr := P.GetLinkOverdueNum(Req, episodeId, tenantId, StepCategoryIds)
	if OverdueNumErr != nil {
		err = EpisodeTaskErr
	}
	// 总计-所有时间段
	var EpisodeTaskNotTimeData map[string]types.EpisodeTask

	var makingNotTimeData map[string]types.MakingList
	// 逾期任务-所有时间段
	var OverdueNumNotTimeData map[string]types.OverDueNumRes
	var GetStepCategoryFinishTaskNotTimeData map[string]types.StepCategoryFinishTask
	if Req.StartTime > 0 && Req.EndTime > 0 {
		var ReqF types.ProductionManageReq
		ReqF = Req
		ReqF.StartTime = 0
		ReqF.EndTime = 0
		EpisodeTaskNotTimeData, err = P.GetEpisodeTaskList(ReqF, episodeId, tenantId, StepCategoryIds)
		makingNotTimeData, err = P.getMakingList(ReqF, episodeId, tenantId, StepCategoryIds)
		OverdueNumNotTimeData, err = P.GetLinkOverdueNum(ReqF, episodeId, tenantId, StepCategoryIds)
		GetStepCategoryFinishTaskNotTimeData, err = P.GetStepCategoryFinishTaskData(ReqF, episodeId, tenantId, StepCategoryIds)
	}

	// 查询未关闭工单
	stepCategoryNotWorkOrder, _ := P.getNotCloseWorkOrder(Req, episodeId, StepCategoryIdList)
	// 计划结束时间
	stepCategoryEpisodePlan, _ := P.getEpisodePlan(episodeId, StepCategoryIdList)
	// 查询已完成的环节任务
	GetStepCategoryFinishTaskData, _ := P.GetStepCategoryFinishTaskData(Req, episodeId, tenantId, StepCategoryIds)
	// 查询环节返修率
	//GetRepairStepCategoryData, _ := P.GetRepairStepCategoryList(Req.ProjectIdList, episodeId, tenantId)
	// 查询环节返修中
	GetStepCategoryRepairIngData, _ := P.GetStepCategoryRepairIngList(Req, episodeId, tenantId, StepCategoryIds)
	// 查询环节总返修数量
	GetStepCategoryRepairNumData, _ := P.GetStepCategoryRepairNumList(Req, episodeId, tenantId, StepCategoryIds)
	// 查询集交付时间,播出时间
	GetEpisodeJsonData, _ := P.GetEpisodeJsonList(episodeId)
	res, err = ProductionCard{}.StepCategoryCardList(episodeData, EpisodeTaskData, EpisodeTaskNotTimeData, makingData, makingNotTimeData,
		OverdueNumData, OverdueNumNotTimeData, StepTaskData, stepCategoryEpisodePlan, stepCategoryNotWorkOrder, GetStepCategoryFinishTaskData, GetStepCategoryFinishTaskNotTimeData,
		GetStepCategoryRepairIngData, GetEpisodeJsonData, GetStepCategoryRepairNumData, Req)
	return
}

// Info 制片管理-详情
func (P ProductionManage) Info(Req types.ProductionManageInfoReq, tenantId int64, page []int) (res []interface{}, err error) {

	var moduleInfo struct {
		Id   uint64 `json:"id"`
		Code string `json:"code"`
	}
	// 剧集
	ClickHouse.DB.Model(&model.Module{}).Select("id,code").Where("code='episode'").First(&moduleInfo)

	where := ClickHouse.DB.Where("entity.tenant_id = ? ", tenantId).
		Where("entity.module_id = ?", moduleInfo.Id)
	if len(Req.ProjectIdList) > 0 {
		where.Where("entity.project_id IN (?)", Req.ProjectIdList)
	}
	// 查询剧集列表
	episodeData, episodeErr := P.GetEpisodeRelationStepList(where, page[0], page[1])
	if episodeErr != nil {
		err = episodeErr
	}

	var episodeId []uint64 // 所有的剧集id
	for _, episodeItem := range episodeData {
		episodeId = append(episodeId, episodeItem.EpisodeId)
	}
	if len(episodeId) <= 0 {
		return
	}

	// 获取当前集下的总计任务
	EpisodeTaskData, _ := P.GetEpisodeTaskData(Req, episodeId, tenantId)
	// 获取当前集下的制作任务
	makingData, _ := P.getStepMakingList(Req, episodeId, tenantId)
	// 获取当前集下的逾期任务
	OverdueNumData, _ := P.GetLinkStepOverdueNum(Req, episodeId, tenantId)
	// 查询返修率的数据
	//getUnderRepairData, _ := P.getUnderRepairStepData(Req, episodeId, tenantId)

	// 周期任务
	var makingNotTimeData map[string]types.StepMakingList
	var OverdueNumNotTimeData map[string]types.OverDueStepNumRes
	var EpisodeTaskNotTimeData map[string]types.StepEpisodeTask
	if Req.StartTime > 0 && Req.EndTime > 0 {
		var ReqF types.ProductionManageInfoReq
		ReqF = Req
		ReqF.EndTime = 0
		ReqF.StartTime = 0
		EpisodeTaskNotTimeData, _ = P.GetEpisodeTaskData(ReqF, episodeId, tenantId)
		makingNotTimeData, _ = P.getStepMakingList(ReqF, episodeId, tenantId)
		OverdueNumNotTimeData, _ = P.GetLinkStepOverdueNum(ReqF, episodeId, tenantId)
	}

	// 获取工序任务列表
	StepTaskData, StepTaskErr := P.getStepTaskList(Req, episodeId, tenantId)
	if StepTaskErr != nil {
		err = StepTaskErr
	}
	// 查询未完成的环节任务
	GetStepFinishTaskData, _ := P.GetStepFinishTaskData(Req, episodeId, tenantId)
	getStepNotCloseWorkData, _ := P.getStepNotCloseWorkOrder(Req, episodeId)
	// 返修中
	GetStepRepairIngData, _ := P.GetStepRepairIngList(Req, episodeId, tenantId)
	// 返修数
	GetStepRepairData, _ := P.GetStepRepairList(Req, episodeId, tenantId)

	res, err = ProductionStepCard{}.StepCardList(episodeData, EpisodeTaskData, EpisodeTaskNotTimeData,
		makingData, makingNotTimeData, OverdueNumData, OverdueNumNotTimeData, StepTaskData, GetStepFinishTaskData,
		getStepNotCloseWorkData, GetStepRepairIngData, GetStepRepairData, Req)
	return
}

// GetEpisodeRelationStepList 获取剧集下的区间任务总计数量
func (P ProductionManage) GetEpisodeTaskList(Req types.ProductionManageReq, episodeId []uint64, tenantId int64, StepCategoryIds []int) (res map[string]types.EpisodeTask, err error) {

	var EpisodeTask []types.EpisodeTask
	query := ClickHouse.DB.Model(&model.Task{}).
		Select("count(task.id) as num,task.step_category_id as StepCategoryId,epr.episode_id as EpisodeId").
		//Joins("JOIN task on entity_episode_relation.entity_id  = task.entity_id").
		Joins("JOIN (select distinct entity_id, episode_id from entity_episode_relation  where episode_id in (?)) epr on task.entity_id = epr.entity_id", episodeId).
		Where("task.tenant_id = ? ", tenantId).
		Where("step_category_id IN (?)", StepCategoryIds)

	if len(Req.ProjectIdList) > 0 {
		query.Where("task.project_id IN (?) ", Req.ProjectIdList)
	}
	if Req.StartTime > 0 && Req.EndTime > 0 {
		query.Where("task.plan_end_time between ? and ?", Req.StartTime, Req.EndTime)
	}
	query.Where("task.step_type = 'step_category'").Group("epr.episode_id,task.step_category_id")
	err = query.
		Find(&EpisodeTask).Error

	res = make(map[string]types.EpisodeTask, len(EpisodeTask))
	for i, data := range EpisodeTask {
		k := fmt.Sprintf("%d-%d", data.EpisodeId, data.StepCategoryId)
		res[k] = EpisodeTask[i]
	}
	return
}

// GetEpisodeRelationStepList 获取集下面的实体
func (P ProductionManage) GetEpisodeRelationStepList(where interface{}, page, num int) (episodeData []types.EpisodeData, err error) {
	err = ClickHouse.DB.Model(&model.Entity{}).
		Select("entity.code as EntityCode,entity.id as EpisodeId").
		Where(where).
		Order("if(simpleJSONExtractUInt(entity.json, 'episode_plan_seal_time') = 0,2999999999,simpleJSONExtractUInt(entity.json,'episode_plan_seal_time')) asc,substringUTF8(entity.code,1,2) desc,length(entity.code) asc,entity.code asc").Offset((page - 1) * num).Limit(num).
		Find(&episodeData).Error
	return
}

// 获取工序任务列表
func (P ProductionManage) getStepTaskList(Req types.ProductionManageInfoReq, episodeId []uint64, tenantId int64) (episodeData []types.StepTaskInfoRes, err error) {

	query := ClickHouse.DB.Model(&model.Task{}).
		Select("step.code as StepCode,step.id as StepId,step.step_category_id as StepCategoryId,step.name as StepName").
		Joins("JOIN (select distinct entity_id, episode_id from entity_episode_relation  where episode_id in (?)) epr on task.entity_id = epr.entity_id", episodeId).
		Joins("inner join step on step.id = task.step_id").
		Where("step_type = 'step'").
		Where("task.tenant_id = ? ", tenantId).
		Where("step.is_dismantle_step = 'no'")
	if len(Req.ProjectIdList) > 0 {
		query.Where("task.project_id IN (?)", Req.ProjectIdList)
	}
	if len(Req.StepCategoryIdList) > 0 {
		query.Where("task.step_category_id IN (?)", Req.StepCategoryIdList)
	}
	err = query.Group("step.code,step.id,step.step_category_id,step.name").Order("step.step_category_id asc").
		Find(&episodeData).Error
	return
}

type planData struct {
	EntityId       uint64 `json:"entity_id"`
	StepCategoryId uint64 `json:"step_category_id"`
	StartTime      int64  `json:"start_time"`
	EndTime        int64  `json:"end_time"`
}

type notCloseWorkOrder struct {
	EpisodeId      uint64 `json:"episode_id"`
	StepCategoryId uint64 `json:"step_category_id"`
	Num            uint64 `json:"num"`
}

// 查询剧集分类计划
func (P ProductionManage) getEpisodePlan(episodeData []uint64, categoryColumnMaps []int) (res map[string]planData, err error) {

	var planDataList []planData

	err = ClickHouse.DB.Model(&model.Plan{}).
		Where("entity_id in ? and step_category_id in ?", episodeData, categoryColumnMaps).
		Where("type = 'step_category'").
		Select("entity_id,step_category_id,start_time,end_time").Find(&planDataList).Error

	if err != nil {
		return
	}
	res = make(map[string]planData, len(planDataList))
	for i, data := range planDataList {
		k := fmt.Sprintf("%d-%d", data.EntityId, data.StepCategoryId)
		res[k] = planDataList[i]
	}
	return
}

// getNotCloseWorkOrder 查询未关闭的工单
func (P ProductionManage) getNotCloseWorkOrder(Req types.ProductionManageReq, episodeId []uint64, categoryColumnMaps []int) (res map[string]notCloseWorkOrder, err error) {

	var workOrderList []notCloseWorkOrder
	query := ClickHouse.DB.Model(&model.TaskWorkOrder{}).
		Joins("JOIN (select distinct entity_id, episode_id from entity_episode_relation  where episode_id in ?) epr on task_work_order.entity_id = epr.entity_id", episodeId).
		Where("status in (?)", []uint64{0, 3, 4})
	if len(Req.ProjectIdList) > 0 {
		query.Where("task_work_order.project_id in (?)", Req.ProjectIdList)
	}
	err = query.Where("step_category_id in ?", categoryColumnMaps).
		Select("task_work_order.step_category_id, count(task_work_order.id) as num, epr.episode_id").
		Group("epr.episode_id,task_work_order.step_category_id").Find(&workOrderList).Error

	if err != nil {
		return
	}
	res = make(map[string]notCloseWorkOrder, len(workOrderList))
	for i, data := range workOrderList {
		k := fmt.Sprintf("%d-%d", data.EpisodeId, data.StepCategoryId)
		res[k] = workOrderList[i]
	}
	return
}

// getStepNotCloseWorkOrder 查询工序未关闭的工单
func (P ProductionManage) getStepNotCloseWorkOrder(Req types.ProductionManageInfoReq, episodeData []uint64) (res map[string]notCloseWorkOrder, err error) {

	var workOrderList []notCloseWorkOrder
	query := ClickHouse.DB.Model(&model.EntityEpisodeRelation{}).
		Joins("join task_work_order two on entity_episode_relation.entity_id = two.entity_id").
		Where("status in (?)", []uint64{0, 3, 4})
	if len(Req.ProjectIdList) > 0 {
		query.Where("two.project_id in (?)", Req.ProjectIdList)
	}
	err = query.Where("entity_episode_relation.episode_id in ? and step_category_id in ?", episodeData, Req.StepCategoryIdList).
		Select("two.step_id, count(two.id) as num, entity_episode_relation.episode_id").
		Group("entity_episode_relation.episode_id,two.step_id").Find(&workOrderList).Error

	if err != nil {
		return
	}
	res = make(map[string]notCloseWorkOrder, len(workOrderList))
	for i, data := range workOrderList {
		k := fmt.Sprintf("%d-%d", data.EpisodeId, data.StepCategoryId)
		res[k] = workOrderList[i]
	}
	return
}

//TodayCount 今日统计
func (P ProductionManage) TodayCount(ctx *gin.Context, req types.TodayCountReq) (res types.TodayCountRes, err error) {

	var s, e, current int64
	current = time.Now().Unix()
	if req.StartTime > 0 {
		s = req.StartTime
	} else {
		var todayStart = time.Now().Format("2006-01-02")
		todayStartUnix, err := time.ParseInLocation("2006-01-02", todayStart, time.Local)
		if err != nil {
			return res, err
		}
		s = todayStartUnix.Unix()
	}

	if req.EndTime > 0 {
		e = req.EndTime
	} else {
		e = s + 60*60*24
	}
	var userService User
	userInfo, err := userService.GetMyUserInfo(ctx)
	if err != nil {
		return res, err
	}

	var projectMemberUserIdList []int64
	switch req.SpecialRoleFilter {
	case "director":
		RoleService := Role{}
		directorRoleRes, err := RoleService.Find(ctx, "director")
		if err != nil {
			return res, err
		}
		projectMemberService := ProjectMember{}
		projectMemberList, err := projectMemberService.Select(ctx, req.ProjectId, directorRoleRes.Data.ID)
		if err != nil || len(projectMemberList.Data.Rows) == 0 {
			return res, err
		}
		for _, row := range projectMemberList.Data.Rows {
			projectMemberUserIdList = append(projectMemberUserIdList, row.UserID)
		}
		break
	}

	var taskIds []int64
	if req.DateType == "delay_created" {
		module := model.Module{}
		taskModule, err := module.GetByCode("task")
		if err != nil {
			return res, err
		}
		err = ClickHouse.DB.Model(&model.ReviewRequest{}).Where("module_id = ? and created BETWEEN ? and ?", taskModule.Id, s, e).Pluck("link_id", &taskIds).Error
		if len(taskIds) == 0 && err != nil {
			return res, err
		}

	}

	err = P.getTodayBaseQuery(req, userInfo, s, e, projectMemberUserIdList, taskIds).
		Pluck("count(distinct task.id) as Total", &res.Total).Error
	if err != nil {
		return
	}

	err = P.getTodayBaseQuery(req, userInfo, s, e, projectMemberUserIdList, taskIds).
		Where("simpleJSONExtractInt(task.json, 'task_status') IN (7,8)").
		Pluck("count(distinct task.id) as PlanDone", &res.Done).Error
	if err != nil {
		return
	}

	err = P.getTodayBaseQuery(req, userInfo, s, e, projectMemberUserIdList, taskIds).
		Where("simpleJSONExtractInt(task.json, 'task_status') in (select id from status where correspond = 'in_progress')").
		Pluck("count(distinct task.id) as Inprogress", &res.Inprogress).Error
	if err != nil {
		return
	}
	err = P.getTodayBaseQuery(req, userInfo, s, e, projectMemberUserIdList, taskIds).
		Joins("LEFT JOIN (select task_id from task_work_order where status = 0 group by task_id) task_work_order_temp on task_work_order_temp.task_id = task.id").
		Where("(task.step_type = 'step' and ("+
			"task.assign_status = 'default' "+
			"or simpleJSONExtractInt(task.json, 'task_status') in (select id from status where code in ('not_started','ready_to_start','wait_assemble'))) "+
			"and task.plan_end_time between 1 and ? and simpleJSONExtractInt(task.json, 'task_status') not in (3, 7)) "+
			"or (task.plan_end_time between 1 and ? and simpleJSONExtractInt(task.json, 'task_status') not in (3, 7)) "+
			"or task_work_order_temp.task_id > 0  ", current, current).
		Pluck("count(distinct task.id) as Abnormal", &res.Abnormal).Error
	if err != nil {
		return
	}
	if req.IsMyResponsible {
		// 查询未完成的任务数
		err = P.getTodayBaseQuery(req, userInfo, s, e, projectMemberUserIdList, taskIds).
			Where("simpleJSONExtractInt(task.json, 'task_status') IN (select id from status where code not in ('ready_to_publish','final','closed'))").
			Pluck("count(distinct task.id) as NotFinalNum", &res.NotFinalNum).Error

		// 查询未开始
		var StatusService Status
		notStartedStatusList, err := StatusService.GetNotStartedStatus()
		if err != nil {
			return res, err
		}
		var notStartedStatusIds []string
		for _, notStartedStatusItem := range notStartedStatusList {
			notStartedStatusIds = append(notStartedStatusIds, strconv.FormatInt(notStartedStatusItem.Id, 10))
		}
		err = P.getTodayBaseQuery(req, userInfo, s, e, projectMemberUserIdList, taskIds).
			Where("simpleJSONExtractInt(task.json, 'task_status') IN (?)", notStartedStatusIds).
			Pluck("count(distinct task.id) as NotStartNum", &res.NotStartNum).Error
		if err != nil {
			return res, err
		}
		// 查询返修
		err = P.getTodayBaseQuery(req, userInfo, s, e, projectMemberUserIdList, taskIds).
			Joins("JOIN repair_order_affected_task roat on task.id = roat.task_id").
			Pluck("count(roat.task_id or null) as RepairNum", &res.RepairNum).Error
		if err != nil {
			return res, err
		}
	}
	return
}

// getTodayBaseQuery
func (P ProductionManage) getTodayBaseQuery(req types.TodayCountReq,
	userInfo types.GetMyUserInfoRes, todayStartUnix, todayEndUnix int64,
	projectMemberUserIdList []int64, delayTaskIds []int64) (res *gorm.DB) {

	rStepCategoryJoined := false
	res = ClickHouse.DB.Model(&model.Task{})
	res = res.Joins("LEFT JOIN task_member on task_member.task_id = task.id")
	if userInfo.Data.Tenant.ID > 0 {
		res = res.Where("task.tenant_id = ?", userInfo.Data.Tenant.ID)
	}
	if req.Executor > 0 { // 如果查询指定执行人
		req.SpecialRoleFilter = "artist"
	}
	if len(req.TaskStepType) > 0 {
		res = res.Where("task.step_type in ?", req.TaskStepType)
	}
	// 特殊权限筛选
	switch req.SpecialRoleFilter {
	case "artist":
		req.DepartmentId = 0
		userId, err := GetSaasUserIdByUnionId(userInfo.Data.User.ID)
		if err != nil {
			return
		}
		if req.Executor > 0 { // 如果查询指定执行人
			res = res.Where("task_member.partner = ?", req.Executor)
		}

		if req.IsMyResponsible { // [我负责的任务]模块
			if req.DepartmentId > 0 {
				res = res.Where("task.department_id = ?", req.DepartmentId)
			} else if len(req.ExecutorUserIdList) == 0 && len(req.TodoStepCategoryId) == 0 {
				var departmentManagerDepartmentIdList []int64
				for _, v := range userInfo.Data.DepartmentInfo {
					if v.RoleCode == "headman" || v.RoleCode == "step_producer" {
						departmentManagerDepartmentIdList = append(departmentManagerDepartmentIdList, v.DepartmentID)
					}
				}
				if len(departmentManagerDepartmentIdList) == 0 {
					return
				}
				res = res.Where(" task.department_id in (?)", departmentManagerDepartmentIdList)
			}
		} else if !req.IsMyResponsible && req.Executor <= 0 {
			res = res.Where("task_member.partner = ?", userId)
		}
		break
	case "headman":
		var departmentManagerDepartmentIdList []int64
		for _, v := range userInfo.Data.DepartmentInfo {
			if v.RoleCode == "headman" || v.RoleCode == "step_producer" {
				departmentManagerDepartmentIdList = append(departmentManagerDepartmentIdList, v.DepartmentID)
			}
		}
		if len(departmentManagerDepartmentIdList) == 0 {
			return
		}

		res = res.Where("task.department_id in ?", departmentManagerDepartmentIdList)
		break
	case "director":
		res = res.Where("task_member.partner in (?)", projectMemberUserIdList)
		break

	}
	if len(req.TodoStepCategoryId) > 0 {
		if !rStepCategoryJoined {
			res = res.
				Joins("JOIN (select * from task_relation_tag where link_module_code in ('step_category','show_step_category')) r_step_category on r_step_category.task_id = task.id")
			rStepCategoryJoined = true
		}
		res = res.Where("r_step_category.link_id in ?", req.TodoStepCategoryId)
	}

	if req.ProjectId > 0 {
		res.Where("task.project_id = ? ", req.ProjectId)
	}
	if req.DepartmentId > 0 {
		res.Where("task.department_id = ?", req.DepartmentId)
	}
	if len(req.ExecutorUserIdList) > 0 {
		res.Where("task_member.partner in (?)", req.ExecutorUserIdList)
	}

	if req.DateType == "delivery" {
		res.Where("task.plan_delivery_time between ? and ?", req.StartTime, req.EndTime)
	} else if req.DateType == "demand_add" { //新增
		res = res.Where("task.created BETWEEN ? and ? and JSONExtractString(task.json,'task_is_append') ='yes'", todayStartUnix, todayEndUnix)
	} else if req.DateType == "delay_created" { //延期
		res = res.Where("task.id in ?", delayTaskIds)
	} else if req.DateType == "delivery_actually" { // 实际交付筛选
		res = res.Where("task.delivery_time BETWEEN ? and ? and JSONExtractString(task.json,'task_status') = 7", req.StartTime, req.EndTime)
	} else {
		res = res.Where("task.plan_end_time BETWEEN ? and ?", todayStartUnix, todayEndUnix)
	}

	if req.OnlyNotDone {
		res = res.Where("simpleJSONExtractInt(task.json, 'task_status') <> (select id from status where code = 'final')")
	}

	res = res.Where("task.step_type <> 'step_category'").
		Where("JSONLength(JSONExtractString(task.json, 'task_deprecate_data')) = 0 and simpleJSONExtractInt(task.json,'task_status') <> 3")
	return
}

type episodeStepCategoryCountSingleColumn struct {
	EpisodeId      int64 `json:"episode_id"`
	StepCategoryId int64 `json:"step_category_id"`
	Count          int64 `json:"count"`
}

//ProgressCount 进度统计
func (P ProductionManage) ProgressCount(ctx *gin.Context, req types.ProgressCountReq) (res []types.ProgressCountResItem, err error) {

	var todayStart = time.Now().Format("2006-01-02")
	todayStartUnix, err := time.ParseInLocation("2006-01-02", todayStart, time.Local)
	if err != nil {
		return
	}
	todayEndUnix := todayStartUnix.AddDate(0, 0, 1)
	var optionService Option
	projectShowStepCategoryList, err := optionService.GetProjectShowStepCategoryListConfig(ctx)
	if err != nil {
		return
	}

	var showStepCategoryIdList []int
	var resNameMap = make(map[string]*types.ProgressCountResItem)
	resIndex := 0
	for _, v := range projectShowStepCategoryList.Data {
		showStepCategoryIdList = append(showStepCategoryIdList, v.ID)
	}
	if len(showStepCategoryIdList) == 0 {
		return
	}

	// 查询异常情况
	totalTodayAbnormalList, err := P.getTotalTodayAbnormalData(req.ProjectId, showStepCategoryIdList)
	if err != nil {
		return
	}
	var totalTodayAbnormalMapData = make(map[string]bool)
	for _, abnormalDatum := range totalTodayAbnormalList {
		totalTodayAbnormalMapData[fmt.Sprintf("%d-%s", abnormalDatum.StepCategoryId, "today")] = abnormalDatum.TodayAbnormalNumber > 0
		totalTodayAbnormalMapData[fmt.Sprintf("%d-%s", abnormalDatum.StepCategoryId, "total")] = abnormalDatum.TotalAbnormalNumber > 0
	}

	var stepCategoryCountList []types.StepCategoryProgressCount
	err = ClickHouse.DB.Model(&model.Task{}).
		Joins("join (select * from task_relation_tag where project_id =? and link_module_code in ('step_category', 'show_step_category') and "+
			"link_id in ?) trt on task.id = trt.task_id", req.ProjectId, showStepCategoryIdList).
		Where("task.project_id = ? and task.entity_module_id <> 71 and JSONLength(JSONExtractString(json, 'task_deprecate_data')) = 0 and simpleJSONExtractInt(task.json, 'task_status') <> 3", req.ProjectId).
		Select("trt.link_id as step_category_id,"+
			"count(task.id) total_task,"+
			"count(simpleJSONExtractInt(task.json, 'task_status') = 7 or null) done_task,"+
			"count(((task.plan_end_time between ? and ?) or (task.plan_end_time > 0 and task.plan_end_time < ? and task.end_time = 0)) or null) today_total_task,"+
			"count((task.plan_end_time between ? and ? and simpleJSONExtractInt(task.json, 'task_status') = 7) or null) today_done_task", todayStartUnix.Unix(), todayEndUnix.Unix(), todayStartUnix.Unix(), todayStartUnix.Unix(), todayEndUnix.Unix()).
		Group("trt.link_id").
		Find(&stepCategoryCountList).
		Error

	if err != nil {
		return
	}
	var stepCategoryCountMap = make(map[int]*types.StepCategoryProgressCount)
	for i, count := range stepCategoryCountList {
		stepCategoryCountMap[count.StepCategoryId] = &stepCategoryCountList[i]
	}

	from := GetFirstDayOfMonth(time.Now())
	to := GetLastDayOfMonth(time.Now())
	to = time.Date(to.Year(), to.Month(), to.Day(), 23, 59, 59, 0, to.Location())
	var pqRes []PlanEpisodeStepCategory

	err = ClickHouse.DB.Model(model.Plan{}).
		Joins("LEFT JOIN (select * from task_relation_tag where link_module_code in ('step_category','show_step_category')) r_step_category on r_step_category.task_id = plan.task_id "+
			"LEFT JOIN (select * from task_relation_tag where link_module_code in ('episode')) r_episode on r_episode.task_id = plan.task_id").
		Where("plan.scope='single' and plan.type = 'step_category' and plan.project_id = ?", req.ProjectId).
		Where("plan.end_time between ? and ?", from.Unix(), to.Unix()).
		Group("r_episode.link_id,r_step_category.link_id").Select("r_episode.link_id as episode_id,r_step_category.link_id as step_category_id").Find(&pqRes).Error
	if err != nil {
		return
	}

	var episodeStepCategoryCountList []types.EpisodeStepCategoryProgressCount
	//var episodeTodoStepCategoryCountList []types.EpisodeStepCategoryProgressCount

	if len(pqRes) > 0 {
		episodeStepCategoryCountList, err = P.getEpisodeStepCategoryCountList(pqRes, req.ProjectId)
		if err != nil {
			return
		}
		//episodeTodoStepCategoryCountList, err = P.getEpisodeTodoStepCategoryCountList(pqRes)
		//if err != nil {
		//	return
		//}
	}

	var episodeStepCategoryCountMap = make(map[string]*types.EpisodeStepCategoryProgressCount)
	for i, count := range episodeStepCategoryCountList {
		episodeStepCategoryCountMap[fmt.Sprintf("%d#%d", count.EpisodeId, count.StepCategoryId)] = &episodeStepCategoryCountList[i]
	}

	//for i, count := range episodeTodoStepCategoryCountList {
	//	tempUniqueKey := fmt.Sprintf("%d#%d", count.EpisodeId, count.StepCategoryId)
	//	if _, ok := episodeStepCategoryCountMap[tempUniqueKey]; ok {
	//		episodeStepCategoryCountMap[fmt.Sprintf("%d#%d", count.EpisodeId, count.StepCategoryId)].TotalCount += count.TotalCount
	//		episodeStepCategoryCountMap[fmt.Sprintf("%d#%d", count.EpisodeId, count.StepCategoryId)].DoneCount += count.DoneCount
	//	} else {
	//		episodeStepCategoryCountMap[fmt.Sprintf("%d#%d", count.EpisodeId, count.StepCategoryId)] = &episodeTodoStepCategoryCountList[i]
	//	}
	//}

	monthEpisodeAbnormalData, err := P.getMonthEpisodeAbnormalData(pqRes, req.ProjectId, showStepCategoryIdList)
	if err != nil {
		return
	}
	var monthEpisodeAbnormalMapData = make(map[string]int64, 0)
	for _, datum := range monthEpisodeAbnormalData {
		monthEpisodeAbnormalMapData[fmt.Sprintf("%d-%d", datum.EpisodeId, datum.StepCategoryId)] = datum.AbnormalNumber
	}

	var episodeList []model.Entity

	err = ClickHouse.DB.Model(&model.Entity{}).Where("project_id = ? and module_id = (select id from module where code = 'episode' limit 1)", req.ProjectId).Select("id,name,code").Find(&episodeList).Error
	if err != nil {
		return
	}

	var episodeIdMap = make(map[int64]*model.Entity)
	var episodeCodeMap = make(map[string]*model.Entity)
	for i, entity := range episodeList {
		episodeIdMap[int64(entity.Id)] = &episodeList[i]
		episodeCodeMap[entity.Code] = &episodeList[i]
	}

	var TotalProgressTotal, TotalProgressDone, TodayProgressDone, TodayProgressTotal int64
	var stepCategoryShouldDoneEpisodeMap = make(map[string]int)
	var moduleCodeMap = make(map[string]bool)
	for _, v := range projectShowStepCategoryList.Data {
		TotalProgressTotal = 0
		TotalProgressDone = 0
		TodayProgressTotal = 0
		TodayProgressDone = 0
		if _, ok := stepCategoryCountMap[v.ID]; ok {
			TotalProgressTotal = stepCategoryCountMap[v.ID].TotalTask
			TotalProgressDone = stepCategoryCountMap[v.ID].DoneTask
			TodayProgressTotal = stepCategoryCountMap[v.ID].TodayTotalTask
			TodayProgressDone = stepCategoryCountMap[v.ID].TodayDoneTask
		}

		if _, ok := resNameMap[v.ShowName]; ok {
			resNameMap[v.ShowName].CategoryIdList = append(resNameMap[v.ShowName].CategoryIdList, int64(v.ID))
			resNameMap[v.ShowName].TotalProgressTotal += TotalProgressTotal
			resNameMap[v.ShowName].TotalProgressDone += TotalProgressDone
			resNameMap[v.ShowName].TodayProgressTotal += TodayProgressTotal
			resNameMap[v.ShowName].TodayProgressDone += TodayProgressDone
			if _, ok = moduleCodeMap[v.ShowName+v.ModuleCode]; !ok {
				resNameMap[v.ShowName].ModuleCodeList = append(resNameMap[v.ShowName].ModuleCodeList, v.ModuleCode)
				moduleCodeMap[v.ShowName+v.ModuleCode] = true
			}
		} else {
			moduleCodeMap[v.ShowName+v.ModuleCode] = true
			res = append(res, types.ProgressCountResItem{
				Type:                   "step_category",
				CategoryIdList:         []int64{int64(v.ID)},
				ModuleCodeList:         []string{v.ModuleCode},
				CategoryName:           v.ShowName,
				TotalProgressTotal:     TotalProgressTotal,
				TotalProgressDone:      TotalProgressDone,
				TodayProgressTotal:     TodayProgressTotal,
				TodayProgressDone:      TodayProgressDone,
				CurrentMonthShouldDone: []types.CurrentMonthShouldDoneItem{},
			})
			resNameMap[v.ShowName] = &res[resIndex]
			resIndex += 1
		}
		if totalTodayAbnormalMapData[fmt.Sprintf("%d-%s", v.ID, "today")] {
			resNameMap[v.ShowName].TodayProgressAbnormal = true
		}
		if totalTodayAbnormalMapData[fmt.Sprintf("%d-%s", v.ID, "total")] {
			resNameMap[v.ShowName].TotalProgressAbnormal = true
		}

		currentMonthDoneEpisodeIndex := len(resNameMap[v.ShowName].CurrentMonthShouldDone) - 1
		for _, entity := range episodeList {
			uniqueKey := fmt.Sprintf("%d#%d", entity.Id, v.ID)
			if _, ok := episodeStepCategoryCountMap[uniqueKey]; ok {
				stepCategoryShouldDoneEpisodeIndexString := fmt.Sprintf("%s#%s", v.ShowName, entity.Name)
				if stepCategoryShouldDoneEpisodeIndex, ok := stepCategoryShouldDoneEpisodeMap[stepCategoryShouldDoneEpisodeIndexString]; ok {
					resNameMap[v.ShowName].CurrentMonthShouldDone[stepCategoryShouldDoneEpisodeIndex].Total += episodeStepCategoryCountMap[uniqueKey].TotalCount
					resNameMap[v.ShowName].CurrentMonthShouldDone[stepCategoryShouldDoneEpisodeIndex].Done += episodeStepCategoryCountMap[uniqueKey].DoneCount
				} else {
					resNameMap[v.ShowName].CurrentMonthShouldDone = append(resNameMap[v.ShowName].CurrentMonthShouldDone, types.CurrentMonthShouldDoneItem{
						EpisodeId:   int64(entity.Id),
						EpisodeName: entity.Name,
						Progress:    0,
						Total:       episodeStepCategoryCountMap[uniqueKey].TotalCount,
						Done:        episodeStepCategoryCountMap[uniqueKey].DoneCount,
					})
					currentMonthDoneEpisodeIndex += 1
					stepCategoryShouldDoneEpisodeMap[stepCategoryShouldDoneEpisodeIndexString] = currentMonthDoneEpisodeIndex
				}
				monthEpisodeAbnormalIndex := fmt.Sprintf("%d-%d", entity.Id, v.ID)
				if monthEpisodeAbnormalMapData[monthEpisodeAbnormalIndex] > 0 {
					resNameMap[v.ShowName].CurrentMonthShouldDone[currentMonthDoneEpisodeIndex].Abnormal = true
				}
			}
		}
	}

	// 查询所有用户是导演的角色
	type projectMemberList struct {
		UserId int64 `json:"user_id"`
	}
	var projectUserList []projectMemberList
	err = ClickHouse.DB.Model(&model.ProjectMember{}).Where("project_id = ? and role_id in (select id from role where code = 'director')", req.ProjectId).Select("user_id").Find(&projectUserList).Error
	if err != nil {
		return
	}
	var directorUserIds []int64
	for _, v := range projectUserList {
		directorUserIds = append(directorUserIds, v.UserId)
	}

	// 查询执行人是导演的任务
	type directorStruct struct {
		TotalCount int64 `json:"total_count"`
		DoneCount  int64 `json:"done_count"`
	}
	var directorStructList []directorStruct
	if len(directorUserIds) > 0 {
		err = ClickHouse.DB.Model(&model.Task{}).
			Joins("JOIN task_member tm on task.id = tm.task_id").
			Joins("JOIN plan p on task.id = p.task_id").
			Where("p.project_id = ?", req.ProjectId).
			Where("p.type IN (?)", []string{"meeting", "review"}).
			Where("task.step_type <> 'step' and JSONLength(JSONExtractString(json, 'task_deprecate_data')) = 0").
			Where("tm.partner in (?)", directorUserIds).
			Select("count(distinct task.id) total_count,count(simpleJSONExtractInt(task.json, 'task_status') = 7 or null) done_count").
			Find(&directorStructList).
			Error
		if err != nil {
			return
		}
	}

	var tmpTotalProgressTotal int64
	var tmpTotalProgressDone int64
	for _, v := range directorStructList {
		tmpTotalProgressTotal += v.TotalCount
		tmpTotalProgressDone += v.DoneCount
	}

	var tmpTodayProgressTotal int64 // 今日总数
	if len(directorUserIds) > 0 {
		err = ClickHouse.DB.Model(&model.Task{}).
			Joins("JOIN task_member tm on task.id = tm.task_id").
			Joins("JOIN plan p on task.id = p.task_id").
			Where("p.project_id = ?", req.ProjectId).
			Where("p.type IN (?)", []string{"meeting", "review"}).
			Where("task.step_type <> 'step' and JSONLength(JSONExtractString(json, 'task_deprecate_data')) = 0").
			Where("tm.partner in (?)", directorUserIds).
			Where("task.plan_end_time between ? and ?", todayStartUnix.Unix(), todayEndUnix.Unix()).
			Select("count(distinct task.id) done_count").
			Pluck("done_count", &tmpTodayProgressTotal).
			Error
		if err != nil {
			return
		}
	}

	var tmpTodayProgressDone int64 // 今日完成数
	if len(directorUserIds) > 0 {
		err = ClickHouse.DB.Model(&model.Task{}).
			Joins("JOIN task_member tm on task.id = tm.task_id").
			Joins("JOIN plan p on task.id = p.task_id").
			Where("p.project_id = ?", req.ProjectId).
			Where("p.type IN (?)", []string{"meeting", "review"}).
			Where("task.step_type <> 'step' and JSONLength(JSONExtractString(json, 'task_deprecate_data')) = 0").
			Where("tm.partner in (?)", directorUserIds).
			Where("simpleJSONExtractInt(task.json, 'task_status') = 7").
			Where("task.plan_end_time between ? and ?", todayStartUnix.Unix(), todayEndUnix.Unix()).
			Select("count(task.id) today_done_task").
			Pluck("today_done_task", &tmpTodayProgressDone).
			Error
		if err != nil {
			return
		}
	}

	// 导演-角色 director
	res = append(res, types.ProgressCountResItem{
		Type:                   "role",
		CategoryIdList:         []int64{},
		CategoryName:           "导演",
		TotalProgressTotal:     tmpTotalProgressTotal,
		TotalProgressDone:      tmpTotalProgressDone,
		TodayProgressTotal:     tmpTodayProgressTotal, // 今日总数
		TodayProgressDone:      tmpTodayProgressDone,  // 今日完成数
		CurrentMonthShouldDone: []types.CurrentMonthShouldDoneItem{},
	})
	return
}

// 查询剧集工序分类任务进度
func (P ProductionManage) getEpisodeStepCategoryCountList(pqRes []PlanEpisodeStepCategory, projectId int64) (res []types.EpisodeStepCategoryProgressCount, err error) {
	if len(pqRes) == 0 {
		return
	}

	var episodeIds []string
	episodeMap := map[int64]bool{}
	var stepCategoryIds []string
	stepCategoryMap := map[int64]bool{}

	epCategoryFilter := ClickHouse.DB
	for _, re := range pqRes {
		epCategoryFilter = epCategoryFilter.Or("r_episode.link_id = ? and r_step_category.link_id = ?", re.EpisodeId, re.StepCategoryId)
		// 去重
		if _, episodeOk := episodeMap[re.EpisodeId]; !episodeOk {
			episodeMap[re.EpisodeId] = true
			episodeIds = append(episodeIds, fmt.Sprintf("%d", re.EpisodeId))
		}

		// 去重
		if _, stepCategoryOk := stepCategoryMap[re.StepCategoryId]; !stepCategoryOk {
			stepCategoryMap[re.StepCategoryId] = true
			stepCategoryIds = append(stepCategoryIds, fmt.Sprintf("%d", re.StepCategoryId))
		}

	}

	//获取剧集任务环节进度数据
	progressDataList, err := P.getEpisodeTaskStepCategoryProgressData(
		epCategoryFilter,
		fmt.Sprintf("link_id in (%s)", strings.Join(stepCategoryIds, ",")),
		fmt.Sprintf("link_id in (%s)", strings.Join(episodeIds, ",")),
		projectId, false)
	for _, progressDataItem := range progressDataList {
		res = append(res, types.EpisodeStepCategoryProgressCount{
			EpisodeId:      progressDataItem.EpisodeId,
			StepCategoryId: progressDataItem.StepCategoryId,
			TotalCount:     progressDataItem.Count,
			DoneCount:      progressDataItem.CompleteCount,
		})
	}
	return
}

// 查询剧集待办进度
func (P ProductionManage) getEpisodeTodoStepCategoryCountList(pqRes []PlanEpisodeStepCategory) (res []types.EpisodeStepCategoryProgressCount, err error) {
	epCategoryFilter := ClickHouse.DB
	for _, re := range pqRes {
		epCategoryFilter = epCategoryFilter.Or("r_episode.link_id = ? and r_step_category.link_id = ?", re.EpisodeId, re.StepCategoryId)
	}

	var todoEpisodeStepCategoryDoneCountMap = make(map[string]*episodeStepCategoryCountSingleColumn)
	var todoEpisodeStepCategoryTotalCountMap = make(map[string]*episodeStepCategoryCountSingleColumn)

	var todoEpisodeStepCategoryTotalCount []episodeStepCategoryCountSingleColumn
	err = ClickHouse.DB.Model(&model.Task{}).
		Joins("LEFT JOIN (select * from task_relation_tag where link_module_code in ('step_category','show_step_category')) r_step_category on r_step_category.task_id = task.id " +
			"LEFT JOIN (select * from task_relation_tag where link_module_code in ('episode')) r_episode on r_episode.task_id = task.id ").
		Where("task.entity_module_id = 60 and JSONLength(JSONExtractString(json, 'task_deprecate_data')) = 0").
		Where(epCategoryFilter).
		Select("r_step_category.link_id step_category_id," +
			"r_episode.link_id episode_id," +
			"count(distinct task.id) count").
		Group("r_step_category.link_id, r_episode.link_id").
		Find(&todoEpisodeStepCategoryTotalCount).
		Error
	if err != nil {
		return
	}
	for i, column := range todoEpisodeStepCategoryTotalCount {
		dataKey := fmt.Sprintf("%d-%d", column.EpisodeId, column.StepCategoryId)
		todoEpisodeStepCategoryTotalCountMap[dataKey] = &todoEpisodeStepCategoryTotalCount[i]
	}

	var todoEpisodeStepCategoryDoneCount []episodeStepCategoryCountSingleColumn
	err = ClickHouse.DB.Model(&model.Task{}).
		Joins("LEFT JOIN (select * from task_relation_tag where link_module_code in ('step_category','show_step_category')) r_step_category on r_step_category.task_id = task.id " +
			"LEFT JOIN (select * from task_relation_tag where link_module_code in ('episode')) r_episode on r_episode.task_id = task.id ").
		Where("task.entity_module_id = 60 and JSONLength(JSONExtractString(json, 'task_deprecate_data')) = 0").
		Where(epCategoryFilter).
		Where("simpleJSONExtractInt(task.json, 'task_status') = 7").
		Select("r_step_category.link_id step_category_id," +
			"r_episode.link_id episode_id," +
			"count(distinct task.id) count").
		Group("r_step_category.link_id, r_episode.link_id").
		Find(&todoEpisodeStepCategoryDoneCount).
		Error

	if err != nil {
		return
	}

	for i, column := range todoEpisodeStepCategoryDoneCount {
		dataKey := fmt.Sprintf("%d-%d", column.EpisodeId, column.StepCategoryId)
		todoEpisodeStepCategoryDoneCountMap[dataKey] = &todoEpisodeStepCategoryDoneCount[i]
	}

	for s, columnRef := range todoEpisodeStepCategoryTotalCountMap {
		var done int64 = 0
		if _, ok := todoEpisodeStepCategoryDoneCountMap[s]; ok {
			done = todoEpisodeStepCategoryDoneCountMap[s].Count
		}
		res = append(res, types.EpisodeStepCategoryProgressCount{
			EpisodeId:      columnRef.EpisodeId,
			StepCategoryId: columnRef.StepCategoryId,
			TotalCount:     columnRef.Count,
			DoneCount:      done,
		})
	}

	return
}

type totalTodayAbnormalData struct {
	StepCategoryId      int   `json:"step_category_id"`
	TotalAbnormal       bool  `json:"total_abnormal"`
	TodayAbnormal       bool  `json:"today_abnormal"`
	TotalAbnormalNumber int64 `json:"total_abnormal_number"`
	TodayAbnormalNumber int64 `json:"today_abnormal_number"`
}

// getTotalTodayAbnormalData 查询总进度，今日进度的异常情况
func (P ProductionManage) getTotalTodayAbnormalData(projectId int64, categoryIdList []int) (res []totalTodayAbnormalData, err error) {
	err = ClickHouse.DB.Raw("select temp.step_category_id,"+
		"count((not_start_time > 30 * 24 * 60 * 60) or (not_done_time > 30 * 24 * 60 * 60) or (work_order_not_handle_time > 30 * 24 * 60 * 60) or null) total_abnormal_number,"+
		"count((not_start_time > 24 * 60 * 60) or (not_done_time > 24 * 60 * 60) or (work_order_not_handle_time > 24 * 60 * 60) or null) today_abnormal_number "+
		//"count((not_start_time > 60 * 60) or (not_done_time > 60 * 60) or (work_order_not_handle_time > 60 * 60) or null) hour_abnormal_number "+
		"from (select task.id id,task.step_category_id step_category_id,status.correspond,if(status.correspond = 'not_started' and task.plan_start_time > 0 and task.plan_start_time < toUnixTimestamp(toDateTime(formatDateTime(now(), '%F %T')), 'Asia/Shanghai'),"+
		"toUnixTimestamp(toDateTime(formatDateTime(now(), '%F %T')), 'Asia/Shanghai') - task.plan_start_time, 0) not_start_time,"+
		"if(status.correspond not in ('not_started', 'done', 'blocked') and task.plan_end_time > 0 and task.plan_end_time < toUnixTimestamp(toDateTime(formatDateTime(now(), '%F %T')), 'Asia/Shanghai'),toUnixTimestamp(toDateTime(formatDateTime(now(), '%F %T')), 'Asia/Shanghai') - task.plan_end_time, 0) not_done_time,"+
		"if(two.task_id > 0 and two.created < toUnixTimestamp(toDateTime(formatDateTime(now(), '%F %T')), 'Asia/Shanghai'), toUnixTimestamp(toDateTime(formatDateTime(now(), '%F %T')), 'Asia/Shanghai') - two.created, 0) work_order_not_handle_time "+
		"from task "+
		"left join (select min(created) created, task_id from task_work_order where status = 0 group by task_id) two on task.id = two.task_id "+
		"left join status on status.id = simpleJSONExtractInt(task.json, 'task_status') "+
		"where task.project_id = ? and task.step_category_id in ? and task.step_type = 'step' and JSONLength(JSONExtractString(task.json, 'task_deprecate_data')) = 0 and simpleJSONExtractInt(task.json,'task_status') <> 3 and ( "+
		"(task.plan_start_time > 0 and task.plan_start_time < toUnixTimestamp(toDateTime(formatDateTime(now(), '%F %T')), 'Asia/Shanghai') and status.correspond in ('not_started') ) "+
		"or ( task.plan_end_time > 0 and task.plan_end_time < toUnixTimestamp(toDateTime(formatDateTime(now(), '%F %T')), 'Asia/Shanghai') and status.correspond not in ('not_started', 'done') ) "+
		"or two.task_id > 0 ) ) temp "+
		"group by temp.step_category_id", projectId, categoryIdList).Find(&res).Error
	if err != nil {
		return
	}

	return

}

type monthAbnormalData struct {
	StepCategoryId int64 `json:"step_category_id"` // 分类id
	EpisodeId      int64 `json:"episode_id"`       // 剧集id
	AbnormalNumber int64 `json:"abnormal_number"`  // 24小时未处理异常数量
}

// getTotalTodayAbnormalData 查询本月交付异常情况
func (P ProductionManage) getMonthEpisodeAbnormalData(pqRes []PlanEpisodeStepCategory, projectId int64, categoryIdList []int) (res []monthAbnormalData, err error) {

	if len(pqRes) == 0 {
		return
	}

	var episodeIds []int64
	var stepCategoryIds []int64
	epCategoryFilter := "("
	for _, re := range pqRes {
		epCategoryFilter += fmt.Sprintf("(r_episode.link_id = %d and r_step_category.link_id = %d) OR", re.EpisodeId, re.StepCategoryId)
		episodeIds = append(episodeIds, re.EpisodeId)
		stepCategoryIds = append(stepCategoryIds, re.StepCategoryId)
	}
	epCategoryFilter = strings.TrimRight(epCategoryFilter, " OR") + ")"

	err = ClickHouse.DB.Raw("select temp.step_category_id step_category_id,temp.episode_id episode_id,"+
		"count(temp.id) abnormal_number "+
		"from (select task.id id, r_step_category.link_id step_category_id, r_episode.link_id episode_id,status.correspond,"+
		"if(status.correspond = 'not_started' and task.plan_start_time > 0 and task.plan_start_time < toUnixTimestamp(toDateTime(formatDateTime(now(), '%F %T')), 'Asia/Shanghai'), toUnixTimestamp(toDateTime(formatDateTime(now(), '%F %T')), 'Asia/Shanghai') - task.plan_start_time, 0) not_start_time, "+
		"if(status.correspond not in ('not_started', 'done', 'blocked') and task.plan_end_time > 0 and task.plan_end_time < toUnixTimestamp(toDateTime(formatDateTime(now(), '%F %T')), 'Asia/Shanghai'), toUnixTimestamp(toDateTime(formatDateTime(now(), '%F %T')), 'Asia/Shanghai') - task.plan_end_time, 0) not_done_time, "+
		"if(two.task_id > 0 and two.created < toUnixTimestamp(toDateTime(formatDateTime(now(), '%F %T')), 'Asia/Shanghai'), toUnixTimestamp(toDateTime(formatDateTime(now(), '%F %T')), 'Asia/Shanghai') - two.created, 0) work_order_not_handle_time "+
		"from task join (select * from task_relation_tag where project_id = ? and link_module_code in ('show_step_category', 'step_category') and link_id in ?) r_step_category on  r_step_category.task_id = task.id "+
		"join (select * from task_relation_tag where project_id = ? and link_module_code = 'episode' and link_id in ?) r_episode on r_episode.task_id = task.id "+
		"left join (select min(created) created, task_id from task_work_order where status = 0 group by task_id) two on task.id = two.task_id "+
		"left join status on status.id = simpleJSONExtractInt(task.json, 'task_status') "+
		"where task.project_id = ?"+" and "+epCategoryFilter+" "+
		"and task.step_type not in ('step') and JSONLength(JSONExtractString(task.json, 'task_deprecate_data')) = 0 and simpleJSONExtractInt(task.json,'task_status') <> 3 "+
		"and ((task.plan_start_time > 0 and task.plan_start_time < toUnixTimestamp(toDateTime(formatDateTime(now(), '%F %T')), 'Asia/Shanghai') and status.correspond in ('not_started')) or (task.plan_end_time > 0 and task.plan_end_time < toUnixTimestamp( toDateTime(formatDateTime(now(), '%F %T')), 'Asia/Shanghai') and status.correspond not in ('not_started', 'done')) or two.task_id > 0)) temp "+
		"where (temp.not_start_time > 24 * 60 * 60) or (temp.not_done_time > 24 * 60 * 60) or (temp.work_order_not_handle_time > 24 * 60 * 60) "+
		"group by temp.step_category_id, temp.episode_id", projectId, stepCategoryIds, projectId, episodeIds, projectId).Find(&res).Error
	return
}

type StepCategoryMaxEndTimeQueryStruct struct {
	StepCategoryId int64 `json:"step_category_id"`
	EndTime        int64 `json:"end_time"`
}

//GetMonthPlanTodoTaskProgress 获取当前月计划代办任务进度
func (P ProductionManage) GetPlanTodoTaskProgress(ctx *gin.Context, projectId int64, episodeId int64) (res []types.GetMonthPlanTodoTaskProgressRes, err error) {
	var optionService Option
	projectShowStepCategoryList, err := optionService.GetProjectShowStepCategoryListConfig(ctx)

	if err != nil {
		return
	}

	var stepCategoryIds []int
	var stepCategoryIdStr []string
	for _, projectShowStepCategoryItem := range projectShowStepCategoryList.Data {
		stepCategoryIds = append(stepCategoryIds, projectShowStepCategoryItem.ID)
		stepCategoryIdStr = append(stepCategoryIdStr, fmt.Sprintf("%d", projectShowStepCategoryItem.ID))
	}

	// 获取该集下的任务统计
	//whereSql := ClickHouse.DB.Where("r_episode.link_id = ? and r_step_category.link_id in ?", episodeId, stepCategoryIds)
	progressDataList, err := P.getEpisodeTaskStepCategoryProgressData(nil,
		fmt.Sprintf("link_id in (%s)", strings.Join(stepCategoryIdStr, ",")),
		fmt.Sprintf("link_id = %d", episodeId),
		projectId, true)

	if err != nil || len(progressDataList) == 0 {
		return
	}

	var scMaxEndTime []StepCategoryMaxEndTimeQueryStruct
	err = ClickHouse.DB.Model(&model.Plan{}).
		Joins("JOIN task_relation_tag trt on plan.task_id = trt.task_id and trt.link_module_code in ('step_category', 'show_step_category')").
		Where("plan.project_id = ? and plan.scope = 'single' and plan.type  ='step_category' and plan.entity_id = ?", projectId, episodeId).
		Select("trt.link_id step_category_id,max(plan.end_time) end_time").
		Group("trt.link_id").
		Find(&scMaxEndTime).Error

	if err != nil {
		return
	}

	scMaxEndTimeMap := map[int64]int64{}
	for _, scMaxEndTimeItem := range scMaxEndTime {
		scMaxEndTimeMap[scMaxEndTimeItem.StepCategoryId] = scMaxEndTimeItem.EndTime
	}

	var meetingList []types.Meeting

	//获取会议
	err = ClickHouse.DB.Model(&model.Plan{}).
		Joins("JOIN task on plan.task_id = task.id").
		Joins("JOIN task_relation_tag r_step_category on plan.task_id = r_step_category.task_id and r_step_category.link_module_code in ('step_category', 'show_step_category')").
		Joins("join task_relation_tag r_episode on task.id = r_episode.task_id and r_episode.link_module_code in ('episode')").
		Where("plan.project_id = ? and  r_episode.link_id = ? and r_step_category.link_id in ? and plan.type = 'meeting'", projectId, episodeId, stepCategoryIds).
		Select("plan.id as id,plan.task_id as task_id,max(r_step_category.link_id) as step_category_id,task.name as name").
		Group("plan.id,plan.task_id,task.name").
		Find(&meetingList).
		Error

	meetingMap := map[int64][]types.Meeting{}

	for _, meetingItem := range meetingList {
		meetingMap[meetingItem.StepCategoryId] = append(meetingMap[meetingItem.StepCategoryId], meetingItem)
	}

	//获取剧集计划封板时间
	var episodeStepCategorySealTimeList []model.EpisodeStepCategorySealTime
	err = ClickHouse.DB.Model(&model.EpisodeStepCategorySealTime{}).
		Where("project_id = ? and entity_id = ?", projectId, episodeId).
		Select("id,entity_id,step_category_ids,seal_time").
		Find(&episodeStepCategorySealTimeList).Error

	if err != nil {
		return
	}

	//获取实际封板时间
	var episode = model.Entity{}
	var episodeJson model.EpisodeJson
	err = ClickHouse.DB.Model(&model.Entity{}).Where("id = ?", episodeId).Select("id,json").Take(&episode).Error
	_ = json.Unmarshal(episode.Json, &episodeJson)

	episodeIsSeal := episodeJson.EpisodeSealTime > 0 && time.Now().Unix() > episodeJson.EpisodeSealTime

	// 剧集分类封板时间处理
	episodeStepCategorySealTimeMap := map[int]bool{}
	for _, episodeStepCategorySealTimeItem := range episodeStepCategorySealTimeList {
		for _, stepCategoryId := range strings.Split(episodeStepCategorySealTimeItem.StepCategoryIDs, ",") {
			currentStepCategoryId, _ := strconv.Atoi(stepCategoryId)
			// 判定当前时间是否超过封板时间
			episodeStepCategorySealTimeMap[currentStepCategoryId] = time.Now().Unix() > episodeStepCategorySealTimeItem.SealTime
		}
	}

	planListMap := map[int64]types.EpisodeTaskStepCategoryProgressData{}
	for _, progressDataListItem := range progressDataList {
		planListMap[progressDataListItem.StepCategoryId] = progressDataListItem
	}

	//根据大分类来合并
	resIndexMap := map[string]int{}
	for _, projectShowStepCategoryItem := range projectShowStepCategoryList.Data {
		currentIsSeal := false
		// 成片code判定 ,此处code 暂时定死,将来可能会有改动
		if projectShowStepCategoryItem.ModuleCode == "color" || projectShowStepCategoryItem.ModuleCode == "dub_in" || projectShowStepCategoryItem.ModuleCode == "sound_mixing" || projectShowStepCategoryItem.ModuleCode == "clip" {
			if episodeIsSeal {
				currentIsSeal = episodeIsSeal
			}
		} else {
			if sealTimeValue, sealTimeOk := episodeStepCategorySealTimeMap[projectShowStepCategoryItem.ID]; sealTimeOk && sealTimeValue {
				currentIsSeal = sealTimeValue
			}
		}

		if _, resIndexOk := resIndexMap[projectShowStepCategoryItem.ShowName]; !resIndexOk {
			resIndexMap[projectShowStepCategoryItem.ShowName] = len(res)

			progressRes := types.GetMonthPlanTodoTaskProgressRes{
				Name:            projectShowStepCategoryItem.ShowName,
				Count:           planListMap[int64(projectShowStepCategoryItem.ID)].Count,
				CompleteCount:   planListMap[int64(projectShowStepCategoryItem.ID)].CompleteCount,
				EndTime:         scMaxEndTimeMap[int64(projectShowStepCategoryItem.ID)],
				StepCategoryIds: []int64{int64(projectShowStepCategoryItem.ID)},
				IsAbnormal:      planListMap[int64(projectShowStepCategoryItem.ID)].AbnormalCount > 0,
				MeetingList:     meetingMap[int64(projectShowStepCategoryItem.ID)],
			}

			if currentIsSeal {
				progressRes.IsSeal = currentIsSeal
			}

			res = append(res, progressRes)
		} else {
			res[resIndexMap[projectShowStepCategoryItem.ShowName]].Count += planListMap[int64(projectShowStepCategoryItem.ID)].Count
			res[resIndexMap[projectShowStepCategoryItem.ShowName]].CompleteCount += planListMap[int64(projectShowStepCategoryItem.ID)].CompleteCount
			res[resIndexMap[projectShowStepCategoryItem.ShowName]].StepCategoryIds = append(res[resIndexMap[projectShowStepCategoryItem.ShowName]].StepCategoryIds, int64(projectShowStepCategoryItem.ID))

			if !res[resIndexMap[projectShowStepCategoryItem.ShowName]].IsAbnormal && planListMap[int64(projectShowStepCategoryItem.ID)].AbnormalCount > 0 {
				res[resIndexMap[projectShowStepCategoryItem.ShowName]].IsAbnormal = planListMap[int64(projectShowStepCategoryItem.ID)].AbnormalCount > 0
			}

			//比较出最大的截至日期
			if scMaxEndTimeMap[int64(projectShowStepCategoryItem.ID)] > res[resIndexMap[projectShowStepCategoryItem.ShowName]].EndTime {
				res[resIndexMap[projectShowStepCategoryItem.ShowName]].EndTime = scMaxEndTimeMap[int64(projectShowStepCategoryItem.ID)]
			}

			// 合并会议列表
			if meetingMapValue, meetingMapOk := meetingMap[int64(projectShowStepCategoryItem.ID)]; meetingMapOk {
				for _, meetingMapItem := range meetingMapValue {
					res[resIndexMap[projectShowStepCategoryItem.ShowName]].MeetingList =
						append(res[resIndexMap[projectShowStepCategoryItem.ShowName]].MeetingList, meetingMapItem)
				}
			}

			if currentIsSeal {
				res[resIndexMap[projectShowStepCategoryItem.ShowName]].IsSeal = currentIsSeal
			}
		}
	}

	//百分比计算
	for resIndex, resItem := range res {
		var currentProgress int64
		if resItem.Count != 0 {
			currentProgress = int64(Decimal(float64(resItem.CompleteCount)/float64(resItem.Count)) * 100)
		}
		resItem.Progress = currentProgress
		res[resIndex] = resItem
	}

	return
}

//GetEpisodeStepCategoryTaskProgressCount 获取
func (P ProductionManage) GetEpisodeStepCategoryTaskProgressCount(projectId int64, stepCategoryIds []int64, episodeId int64) (Count int64, FinishCount int64, AbnormalCount int64, err error) {

	var episodeCode string
	err = ClickHouse.DB.Model(&model.Entity{}).Where("id =?", episodeId).Pluck("code", &episodeCode).Error
	if err != nil {
		return
	}
	//总数
	err = ClickHouse.DB.Model(&model.Entity{}).
		Joins("JOIN task on task.entity_id = entity.id ").
		Where("entity.project_id =? and entity.initial_episode_code = ? and task.step_type = 'step' AND JSONLength(JSONExtractString(task.json, 'task_deprecate_data')) = 0 and simpleJSONExtractInt(task.json,'task_status') <> 3 and task.step_category_id in (?) ", projectId, episodeCode, stepCategoryIds).
		Select("count(distinct task.id) as count").Pluck("count", &Count).Error

	if err != nil {
		return
	}
	//未完成总数
	err = ClickHouse.DB.Model(&model.Entity{}).
		Joins("JOIN task on task.entity_id = entity.id").
		Where("entity.project_id = ? and entity.initial_episode_code = ? and task.step_type = 'step' AND JSONLength(JSONExtractString(task.json, 'task_deprecate_data')) = 0 and simpleJSONExtractInt(task.json,'task_status') NOT in (3,7,8) and task.step_category_id in (?)", projectId, episodeCode, stepCategoryIds).
		Select("count(distinct task.id) as Finish").Pluck("Finish", &FinishCount).Error

	if err != nil {
		return
	}
	//完成的总数
	FinishCount = Count - FinishCount
	//异常
	current := time.Now().Unix()
	err = ClickHouse.DB.Model(&model.Entity{}).
		Joins("LEFT JOIN task on task.entity_id = entity.id ").
		Joins("LEFT JOIN (select task_id from task_work_order where status = 0 group by task_id) task_work_order_temp on task_work_order_temp.task_id = task.id").
		Where("entity.project_id =? and entity.initial_episode_code = ? and task.step_type = 'step' and task.step_category_id in (?) ", projectId, episodeCode, stepCategoryIds).
		Where("(task.step_type = 'step' and ("+
			"task.assign_status = 'default' "+
			"or simpleJSONExtractInt(task.json, 'task_status') in (select id from status where code in ('not_started','ready_to_start','wait_assemble'))) "+
			"and task.plan_end_time between 1 and ? and simpleJSONExtractInt(task.json, 'task_status') not in (3, 7)) "+
			"or (task.plan_end_time between 1 and ? and simpleJSONExtractInt(task.json, 'task_status') not in (3, 7)) "+
			"or task_work_order_temp.task_id > 0  ", current, current).
		Where("JSONLength(JSONExtractString(task.json, 'task_deprecate_data')) = 0 and simpleJSONExtractInt(task.json,'task_status') <> 3").
		Select("count(distinct task.id) as abnormal").
		Pluck("abnormal", &AbnormalCount).Error
	if err != nil {
		return
	}

	return
}

// EpisodeTodoTaskCount 集代办任务
func (P ProductionManage) EpisodeTodoTaskCount(ProjectId int64, StepCategoryIds []int64, EpisodeId int64) (Count int64, FinishCount int64, AbnormalCount int64, err error) {

	// 获取父级分类,通过父级分类,拿取module_code
	stepCategoryId := StepCategoryIds[0]
	var stepCategory model.StepCategory
	ClickHouse.DB.Model(&model.StepCategory{}).Where("id =?", stepCategoryId).Take(&stepCategory)

	var moduleId int64
	if stepCategory.ParentId != 0 {
		ClickHouse.DB.Model(&model.StepCategory{}).Where("id =?", stepCategory.ParentId).Pluck("entity_id", &moduleId)
	} else {
		moduleId = stepCategory.EntityId
	}

	var moduleCode string
	ClickHouse.DB.Model(&model.Module{}).Where("id = ?", moduleId).Pluck("code", &moduleCode)

	err = ClickHouse.DB.Model(&model.Task{}).
		Joins("JOIN task_relation_tag ep_trt on ep_trt.task_id = task.id and ep_trt.link_module_code = 'episode'").
		Joins("JOIN task_relation_tag sc_trt on sc_trt.task_id = task.id and sc_trt.link_module_code in ('step_category','show_step_category')").
		Where("task.step_type IN ('to_do', 'work_order_to_do', 'entity_to_do') and JSONLength(JSONExtractString(task.json, 'task_deprecate_data')) = 0 and simpleJSONExtractInt(task.json,'task_status') <> 3").
		Where("task.project_id = ? and ep_trt.link_id = ? and sc_trt.link_id in ?", ProjectId, EpisodeId, StepCategoryIds).
		Pluck("count(distinct task.id) as total", &Count).Error

	if err != nil {
		return
	}

	err = ClickHouse.DB.Model(&model.Task{}).
		Joins("JOIN task_relation_tag ep_trt on ep_trt.task_id = task.id and ep_trt.link_module_code = 'episode'").
		Joins("JOIN task_relation_tag sc_trt on sc_trt.task_id = task.id and sc_trt.link_module_code in ('step_category','show_step_category')").
		Where("task.step_type IN ('to_do', 'work_order_to_do', 'entity_to_do') and JSONLength(JSONExtractString(task.json, 'task_deprecate_data')) = 0 and simpleJSONExtractInt(task.json,'task_status') <> 3").
		Where("simpleJSONExtractInt(task.json, 'task_status') = 7").
		Where("task.project_id = ? and ep_trt.link_id = ? and sc_trt.link_id in ?", ProjectId, EpisodeId, StepCategoryIds).
		Pluck("count(distinct task.id) as total", &FinishCount).Error

	if err != nil {
		return
	}

	now := time.Now().Unix()
	err = ClickHouse.DB.Model(&model.Task{}).
		Joins("JOIN task_relation_tag ep_trt on ep_trt.task_id = task.id and ep_trt.link_module_code = 'episode'").
		Joins("JOIN task_relation_tag sc_trt on sc_trt.task_id = task.id and sc_trt.link_module_code in ('step_category','show_step_category')").
		Where("task.project_id = ? and ep_trt.link_id = ? and sc_trt.link_id in ?", ProjectId, EpisodeId, StepCategoryIds).
		Where("task.step_type IN ('to_do', 'work_order_to_do', 'entity_to_do') and JSONLength(JSONExtractString(task.json, 'task_deprecate_data')) = 0 and simpleJSONExtractInt(task.json,'task_status') <> 3").
		Where("(  simpleJSONExtractInt(task.json, 'task_status') <> 7 and task.plan_end_time < ?)", now).
		Pluck("count(distinct task.id) as total", &AbnormalCount).Error

	return
}

// EpisodeTaskCount 集任务统计
func (P ProductionManage) EpisodeTaskCount(ProjectId int64, StepCategoryIds []int64, EpisodeId int64) (res []types.EpisodeTaskCountRes, err error) {

	// 获取父级分类,通过父级分类,拿取module_code
	stepCategoryId := StepCategoryIds[0]
	var stepCategory model.StepCategory
	ClickHouse.DB.Model(&model.StepCategory{}).Where("id =?", stepCategoryId).Take(&stepCategory)

	var moduleId int64
	if stepCategory.ParentId != 0 {
		ClickHouse.DB.Model(&model.StepCategory{}).Where("id =?", stepCategory.ParentId).Pluck("entity_id", &moduleId)
	} else {
		moduleId = stepCategory.EntityId
	}

	var moduleCode string
	ClickHouse.DB.Model(&model.Module{}).Where("id = ?", moduleId).Pluck("code", &moduleCode)

	// 如果module 为 asset,level,design -> asset ,storyboard  shot -> shot
	if moduleCode == "asset" || moduleCode == "level" || moduleCode == "design" {
		moduleCode = "asset"
	}

	if moduleCode == "shot" || moduleCode == "storyboard" {
		moduleCode = "shot"
	}

	// 如果不在资产线和镜头线中,则不查出来
	if moduleCode == "asset" || moduleCode == "shot" {
		scCount, scFinishCount, scAbnormalCount, errs := P.GetEpisodeStepCategoryTaskProgressCount(ProjectId, StepCategoryIds, EpisodeId)
		if errs != nil {
			err = errs
			return
		}
		res = append(res, types.EpisodeTaskCountRes{
			ModuleName:    moduleCode,
			Name:          "entity",
			Count:         scCount,
			FinishCount:   scFinishCount,
			AbnormalCount: scAbnormalCount,
		})
	}

	ettCount, ettFinishCount, ettAbnormalCount, err := P.EpisodeTodoTaskCount(ProjectId, StepCategoryIds, EpisodeId)
	if err != nil {
		return
	}
	res = append(res, types.EpisodeTaskCountRes{
		ModuleName:    "todo",
		Name:          "todo",
		Count:         ettCount,
		FinishCount:   ettFinishCount,
		AbnormalCount: ettAbnormalCount,
	})

	return
}

//reviewFeedbackCount 审核反馈统计
func (P ProductionManage) ReviewFeedbackCount(ctx *gin.Context, reviewFeedbackId int64, projectId int64, EpisodeCode string) (res []types.ReviewFeedbackCountRes, err error) {
	var optionService Option
	projectShowStepCategoryList, err := optionService.GetProjectShowStepCategoryListConfig(ctx)

	if err != nil {
		return
	}

	var stepCategoryIds []int
	var parentStepCategoryId []int64
	parentStepCategoryIdMap := map[int64]int64{}
	for _, projectShowStepCategoryItem := range projectShowStepCategoryList.Data {
		stepCategoryIds = append(stepCategoryIds, projectShowStepCategoryItem.ID)

		if _, ok := parentStepCategoryIdMap[projectShowStepCategoryItem.ParentID]; !ok {
			parentStepCategoryId = append(parentStepCategoryId, projectShowStepCategoryItem.ParentID)
			parentStepCategoryIdMap[projectShowStepCategoryItem.ParentID] = projectShowStepCategoryItem.ParentID
		}
	}

	type noteEntityRelationList struct {
		EntityId       int64 `json:"entity_id" gorm:"column:entity_id"`
		StepCategoryId int64 `json:"step_category_id" gorm:"column:step_category_id"`
		ModuleId       int64 `json:"module_id" gorm:"column:module_id"`
	}

	var repairResult []noteEntityRelationList
	// 返修了的
	err = ClickHouse.DB.Model(&model.NoteEntityRelation{}).
		Joins("join note on note.id = note_entity_relation.note_id").
		Joins("join entity on entity.id = note_entity_relation.entity_id").
		Where("entity.initial_episode_code = ?", EpisodeCode).
		Where("note.review_feedback_id = ? and note.demand_status in ('processing','final') and note_entity_relation.step_category_id in ?", reviewFeedbackId, stepCategoryIds).
		Select("note_entity_relation.entity_id as entity_id,note_entity_relation.step_category_id as step_category_id").
		Group("note_entity_relation.entity_id,note_entity_relation.step_category_id").
		Find(&repairResult).Error

	if err != nil {
		return
	}

	var repairCountMap = map[int64]int64{}

	for _, repairResultItem := range repairResult {
		if _, ok := repairCountMap[repairResultItem.StepCategoryId]; !ok {
			repairCountMap[repairResultItem.StepCategoryId] = 1
		} else {
			repairCountMap[repairResultItem.StepCategoryId] += 1
		}
	}

	// 获取模块id
	var parentStepCategoryList []model.StepCategory
	ClickHouse.DB.Model(&model.StepCategory{}).Where("id in ?", parentStepCategoryId).Find(&parentStepCategoryList)

	var moduleId []int64
	moduleIdMap := map[int64]int64{}
	pStepCategoryModuleMap := map[uint64]int64{}
	for _, parentStepCategoryItem := range parentStepCategoryList {
		pStepCategoryModuleMap[parentStepCategoryItem.Id] = parentStepCategoryItem.EntityId

		if _, ok := moduleIdMap[parentStepCategoryItem.EntityId]; !ok {
			moduleIdMap[parentStepCategoryItem.EntityId] = parentStepCategoryItem.EntityId
			moduleId = append(moduleId, parentStepCategoryItem.EntityId)
		}
	}

	entityCountMap, err := P.GetEntityModuleCount(projectId, moduleId, EpisodeCode)

	if err != nil {
		return
	}

	//根据大分类来合并
	resIndexMap := map[string]int{}
	for _, projectShowStepCategoryItem := range projectShowStepCategoryList.Data {
		if _, resIndexOk := resIndexMap[projectShowStepCategoryItem.ShowName]; !resIndexOk {
			resIndexMap[projectShowStepCategoryItem.ShowName] = len(res)
			res = append(res, types.ReviewFeedbackCountRes{
				Name:        projectShowStepCategoryItem.ShowName,
				Color:       projectShowStepCategoryItem.Color,
				Count:       entityCountMap[pStepCategoryModuleMap[uint64(projectShowStepCategoryItem.ParentID)]],
				RepairCount: repairCountMap[int64(projectShowStepCategoryItem.ID)],
			})
		} else {
			res[resIndexMap[projectShowStepCategoryItem.ShowName]].RepairCount += repairCountMap[int64(projectShowStepCategoryItem.ID)]
		}
	}

	//百分比计算
	for resIndex, resItem := range res {
		var currentProgress int64
		if resItem.Count != 0 {
			currentProgress = int64(Decimal(float64(resItem.RepairCount)/float64(resItem.Count)) * 100)
		}
		resItem.Progress = currentProgress
		res[resIndex] = resItem
	}

	return
}

func (P ProductionManage) GetEntityModuleCount(projectId int64, moduleIds []int64, initEpisodeCodes string) (res map[int64]int64, err error) {
	//statusService := Status{}
	//status, err := statusService.GetStatusCodeMap(map[string]string{
	//	"filter": fmt.Sprintf("code in (%s)", strings.Join([]string{"'close'", "'wait_for_merge_sequence'"}, ",")),
	//	"field":  "id,code",
	//})

	//if err != nil {
	//	return
	//}

	//module := model.Module{}
	//
	//moduleMap,err := module.GetByIdsMap(moduleIds)

	var entityCount []struct {
		ModuleId int64 `json:"module_id"  gorm:"column:module_id"`
		Count    int64 `json:"count" gorm:"column:count"`
	}

	err = ClickHouse.DB.Model(&model.Entity{}).
		Where("project_id =? and module_id in ? and initial_episode_code =?", projectId, moduleIds, initEpisodeCodes).
		Select("module_id,count(entity_id) as count").
		Group("module_id").Find(&entityCount).Error

	if err != nil {
		return
	}

	res = map[int64]int64{}
	for _, entityCountItem := range entityCount {
		res[entityCountItem.ModuleId] = entityCountItem.Count
	}

	return
}

//getEpisodeTaskProgressData 获取剧集任务环节进度数据
func (P ProductionManage) getEpisodeTaskStepCategoryProgressData(whereSql *gorm.DB, relationSpTagWhere string, relationEpTagWhere string, projectId int64, isQueryAbnormal bool) (res []types.EpisodeTaskStepCategoryProgressData, err error) {
	//是否查询异常
	fieldList := []string{
		"r_step_category.link_id as step_category_id",
		"r_episode.link_id as episode_id",
		"count(r_step_category.link_id) as count",
		"count(if(simpleJSONExtractInt(task.json, 'task_status') = 7, 1, null)) as complete_count",
	}
	//是否查询异常
	if isQueryAbnormal {
		fieldList = append(fieldList, "count(if((task.assign_status = 'default' or task_work_order_temp.task_id > 0 or simpleJSONExtractInt(task.json, 'task_status') = 1),1, null)) as abnormal_count")
	}
	field := strings.Join(fieldList, ",")

	relationSpTag := fmt.Sprintf("select * from task_relation_tag where project_id = %d and link_module_code in ('show_step_category','step_category')", projectId)

	if relationSpTagWhere != "" {
		relationSpTag += " and " + relationSpTagWhere
	}

	relationEpTag := fmt.Sprintf("select * from task_relation_tag where project_id = %d and link_module_code = 'episode'", projectId)

	if relationEpTagWhere != "" {
		relationEpTag += " and " + relationEpTagWhere
	}

	db := ClickHouse.DB.Model(&model.Task{}).
		Joins(fmt.Sprintf("join (%s) r_step_category on task.id = r_step_category.task_id", relationSpTag)).
		Joins(fmt.Sprintf("join (%s) r_episode on task.id = r_episode.task_id", relationEpTag))

	//是否查询异常
	if isQueryAbnormal {
		db = db.Joins("LEFT JOIN (select task_id from task_work_order where status = 0 group by task_id) task_work_order_temp on task_work_order_temp.task_id = task.id")
	}

	if whereSql != nil {
		db = db.Where(whereSql)
	}

	err = db.Where("task.project_id = ? and JSONLength(JSONExtractString(task.json, 'task_deprecate_data')) = 0 and simpleJSONExtractInt(task.json,'task_status') <> 3 and task.step_type <> 'step_category'", projectId).
		Select(field).
		Group("r_step_category.link_id,r_episode.link_id").
		Find(&res).
		Error

	return
}

//totalTaskCount 总进度详情任务统计
func (P ProductionManage) TotalTaskCount(req types.TotalTaskCountReqFilter) (res []types.TotalTaskCountRes, err error) {
	if req.Type == "" {
		req.Type = "step_category"
	}

	currentNow := time.Unix(req.IsNowMonth, 0)

	var EntityIds []int64
	yearMonthEntityMap := make(map[int64]map[int64][]int64, 0)
	yearMonthTaskNumMap := make(map[int64]map[int64]int64, 0)
	episodeTaskProgressMap := map[int64]int64{}
	type episodeTaskProgress struct {
		Count         int64 `json:"count"`
		CompleteCount int64 `json:"completeCount"`
	}

	directorYearMonthEntityMap := make(map[int64]map[int64][]types.TotalDirectorYearMonthEpisodeTaskProgressRes)

	episodeTaskProgressList := make([]episodeTaskProgress, 0)
	var yearMonthEntityList []struct {
		YearMonth int64 `json:"year_month"`
		Year      int64 `json:"year"`
		Month     int64 `json:"month"`
		EntityId  int64 `json:"entity_id"`
	}

	if req.Type == "step_category" {
		// 找出相关剧集
		err = ClickHouse.DB.Model(&model.Plan{}).
			Joins("join (select task_id from task_relation_tag where link_id in ? and link_module_code in ('show_step_category', 'step_category')) task_relation_tag on task_relation_tag.task_id = plan.task_id", req.CategoryIdList).
			Where("plan.scope = 'single' and plan.type = 'step_category' "+
				"and plan.start_time <= ? and plan.end_time >= ? and plan.project_id = ?", req.EndTime, req.StartTime, req.ProjectId).
			Select("toYYYYMM(toDate(plan.end_time)) AS year_month,toYear(toDate(plan.end_time)) as year,toMonth(toDate(plan.end_time)) as month,entity_id").
			Group("year_month,year,month,entity_id").
			Find(&yearMonthEntityList).
			Error

		if err != nil {
			return
		}

		// 获取剧集id
		for _, yearMonthEntityItem := range yearMonthEntityList {
			year := yearMonthEntityItem.Year
			month := yearMonthEntityItem.Month
			if monthMap, yearOk := yearMonthEntityMap[year]; yearOk {
				if _, monthOk := monthMap[month]; !monthOk {
					yearMonthEntityMap[year][month] = []int64{yearMonthEntityItem.EntityId}
				} else {
					yearMonthEntityMap[year][month] = append(yearMonthEntityMap[year][month], yearMonthEntityItem.EntityId)
				}
			} else {
				yearMonthEntityMap[year] = map[int64][]int64{
					month: {yearMonthEntityItem.EntityId},
				}
			}
			EntityIds = append(EntityIds, yearMonthEntityItem.EntityId)
		}

		// 获取每个月的任务统计数量
		totalTaskNumCount, errs := P.totalYearMonthTaskNumCount(types.TotalTaskEntityCountReq{
			ProjectId:      req.ProjectId,
			EpisodeId:      EntityIds,
			StepCategoryId: req.CategoryIdList,
			StartTime:      req.StartTime,
			EndTime:        req.EndTime,
		})

		if errs != nil {
			err = errs
			return
		}

		for _, totalTaskNumCountItem := range totalTaskNumCount {
			year := totalTaskNumCountItem.Year
			month := totalTaskNumCountItem.Month
			if yearMonth, yearOk := yearMonthTaskNumMap[year]; yearOk {
				if _, monthOk := yearMonth[month]; !monthOk {
					yearMonthTaskNumMap[year][month] = totalTaskNumCountItem.Count
				}
			} else {
				yearMonthTaskNumMap[year] = map[int64]int64{
					month: totalTaskNumCountItem.Count,
				}
			}
		}

		// 获取每月每集的任务统计
		taskProgressRes, errors := P.totalYearMonthEpisodeTaskProgress(types.TotalYearMonthEpisodeTaskProgressReq{
			StepCategoryIds: req.CategoryIdList,
			EpisodeIds:      EntityIds,
			ProjectId:       req.ProjectId,
		})

		if errors != nil {
			err = errors
			return
		}

		// 根据集来合并taskProgressRes统计
		for _, taskProgressResItem := range taskProgressRes {
			if episodeTaskProgressIndex, ok := episodeTaskProgressMap[taskProgressResItem.EpisodeId]; !ok {
				episodeTaskProgressMap[taskProgressResItem.EpisodeId] = int64(len(episodeTaskProgressList))
				episodeTaskProgressList = append(episodeTaskProgressList, episodeTaskProgress{
					Count:         taskProgressResItem.Count,
					CompleteCount: taskProgressResItem.CompleteCount,
				})
			} else {
				episodeTaskProgressList[episodeTaskProgressIndex].Count += taskProgressResItem.Count
				episodeTaskProgressList[episodeTaskProgressIndex].CompleteCount += taskProgressResItem.CompleteCount
			}
		}
	} else {
		// 导演统计
		var userIds []int64
		ClickHouse.DB.Model(&model.ProjectMember{}).Where("project_id = ? and role_code = 'director'", req.ProjectId).Pluck("user_id", &userIds)

		// 去重
		userMap := map[int64]bool{}
		for userIdIndex, userId := range userIds {
			if ok := userMap[userId]; !ok {
				userMap[userId] = true
			} else {
				// 如果存在,删除当前元素
				userIds = append(userIds[:userIdIndex], userIds[userIdIndex+1:]...)
			}
		}

		//获取到剧集
		err = ClickHouse.DB.Model(&model.Plan{}).
			Joins("join (select task_id from task_member where partner in ?) task_member on plan.task_id = task_member.task_id", userIds).
			Joins("join (select link_id,task_id from task_relation_tag where project_id=? and link_module_code in ('episode')) r_episode on plan.task_id = r_episode.task_id", req.ProjectId).
			Where("plan.project_id = ? and plan.type in ('meeting','review') and plan.end_time >= ? and plan.end_time <=?", req.ProjectId, req.StartTime, req.EndTime).
			Select("toYYYYMM(toDate(plan.end_time)) AS year_month,toYear(toDate(plan.end_time)) as year,toMonth(toDate(plan.end_time)) as month,r_episode.link_id as entity_id").
			Group("year_month,year,month,entity_id").
			Find(&yearMonthEntityList).
			Error

		for _, yearMonthEntityItem := range yearMonthEntityList {
			year := yearMonthEntityItem.Year
			month := yearMonthEntityItem.Month

			if yearMonth, yearOk := yearMonthEntityMap[year]; yearOk {
				if _, monthOk := yearMonth[month]; !monthOk {
					yearMonthTaskNumMap[year][month] = yearMonthEntityItem.EntityId
				}
			} else {
				yearMonthTaskNumMap[year] = map[int64]int64{
					month: yearMonthEntityItem.EntityId,
				}
			}

			EntityIds = append(EntityIds, yearMonthEntityItem.EntityId)
		}

		//查询任务总数
		directorYearMonthTaskNum, errs := P.totalDirectorYearMonthTaskNumCount(userIds, req.ProjectId, EntityIds, req.StartTime, req.EndTime)
		if errs != nil {
			err = errs
			return
		}

		for _, directorYearMonthTaskNumItem := range directorYearMonthTaskNum {
			year := directorYearMonthTaskNumItem.Year
			month := directorYearMonthTaskNumItem.Month

			if monthValue, yearOk := yearMonthTaskNumMap[year]; yearOk {
				if _, monthOk := monthValue[month]; !monthOk {
					yearMonthTaskNumMap[year][month] = directorYearMonthTaskNumItem.Count
				}
			} else {
				yearMonthTaskNumMap[year] = map[int64]int64{
					month: directorYearMonthTaskNumItem.Count,
				}
			}
		}

		//统计导演每月集任务进度
		directorYearMonthEntityList, errors := P.totalDirectorYearMonthEpisodeTaskProgress(userIds, req.ProjectId, EntityIds, req.StartTime, req.EndTime)
		if errors != nil {
			err = errors
			return
		}

		// 根据集来合并taskProgress map
		for _, directorYearMonthEntityItem := range directorYearMonthEntityList {
			year := directorYearMonthEntityItem.Year
			month := directorYearMonthEntityItem.Month

			if monthMap, yearOk := directorYearMonthEntityMap[year]; yearOk {
				if _, monthOk := monthMap[month]; !monthOk {
					directorYearMonthEntityMap[year][month] = []types.TotalDirectorYearMonthEpisodeTaskProgressRes{
						directorYearMonthEntityItem,
					}
				} else {
					directorYearMonthEntityMap[year][month] = append(directorYearMonthEntityMap[year][month], directorYearMonthEntityItem)
				}
			} else {
				directorYearMonthEntityMap[year] = map[int64][]types.TotalDirectorYearMonthEpisodeTaskProgressRes{
					month: {directorYearMonthEntityItem},
				}
			}
		}
	}

	// 查询剧集信息
	var episodeList []model.Entity
	err = ClickHouse.DB.Model(&model.Entity{}).Where("id in ?", EntityIds).Select("id,name").Find(&episodeList).Error
	if err != nil {
		return
	}

	episodeMap := map[int64]string{}
	for _, episodeItem := range episodeList {
		episodeMap[int64(episodeItem.Id)] = episodeItem.Name
	}

	// 年月 填补 剧集数据 任务数量
	yearMonthList, err := P.getMonthList(req.StartTime, req.EndTime)

	if err != nil {
		return
	}

	for year, monthList := range yearMonthList {
		var countMonthList []types.TotalTaskCountMonthRes
		for _, month := range monthList {
			// 剧集列表

			var episodeNameList []types.TotalTaskCountMonthEpisodeRes
			if req.Type == "step_category" {
				if episodeIds, ok := yearMonthEntityMap[year][month]; ok {
					for _, episodeId := range episodeIds {
						if taskProgressValue, progressOk := episodeTaskProgressMap[episodeId]; progressOk {
							progress := episodeTaskProgressList[taskProgressValue]
							episodeNameList = append(episodeNameList, types.TotalTaskCountMonthEpisodeRes{
								EpisodeId:    episodeId,
								EpisodeName:  episodeMap[episodeId],
								Progress:     IntVal((float64(progress.CompleteCount) / float64(progress.Count)) * 100),
								FinalTaskNum: progress.CompleteCount,
								TotalTaskNum: progress.Count,
							})
						}
					}
				}
			} else {
				if directorYearMonthEntityItem, ok := directorYearMonthEntityMap[year][month]; ok {
					for _, directorYearMonthEntityValue := range directorYearMonthEntityItem {

						episodeNameList = append(episodeNameList, types.TotalTaskCountMonthEpisodeRes{
							EpisodeId:    directorYearMonthEntityValue.EpisodeId,
							EpisodeName:  episodeMap[directorYearMonthEntityValue.EpisodeId],
							FinalTaskNum: directorYearMonthEntityValue.CompleteCount,
							Progress:     IntVal((float64(directorYearMonthEntityValue.CompleteCount) / float64(directorYearMonthEntityValue.Count)) * 100),
							TotalTaskNum: directorYearMonthEntityValue.Count,
						})
					}
				}
			}
			isNowMonth := "no"
			if int64(currentNow.Year()) == year && int64(currentNow.Month()) == month {
				isNowMonth = "yes"
			}
			countMonthList = append(countMonthList, types.TotalTaskCountMonthRes{
				IsNowMonth:      isNowMonth,
				MonthName:       month,
				TaskNum:         yearMonthTaskNumMap[year][month],
				EpisodeNameList: episodeNameList,
			})
		}
		res = append(res, types.TotalTaskCountRes{
			Year:  year,
			Month: countMonthList,
		})
	}

	return
}

//totalTaskCount
func (P ProductionManage) totalYearMonthEpisodeTaskProgress(req types.TotalYearMonthEpisodeTaskProgressReq) (res []types.TotalYearMonthEpisodeTaskProgressRes, err error) {
	//whereSql := ClickHouse.DB.Where("r_step_category.link_id in ? and r_episode.link_id in ?", req.StepCategoryIds, req.EpisodeIds)

	var stepCategoryStr []string
	stepCategoryMap := map[int64]bool{}
	var episodeIdStr []string
	episodeIdMap := map[int64]bool{}
	for _, stepCategoryId := range req.StepCategoryIds {
		if _, stepCategoryOk := stepCategoryMap[stepCategoryId]; !stepCategoryOk {
			stepCategoryMap[stepCategoryId] = true
			stepCategoryStr = append(stepCategoryStr, fmt.Sprintf("%d", stepCategoryId))
		}
	}

	for _, episodeId := range req.EpisodeIds {
		if _, episodeIdOk := episodeIdMap[episodeId]; !episodeIdOk {
			episodeIdMap[episodeId] = true
			episodeIdStr = append(episodeIdStr, fmt.Sprintf("%d", episodeId))
		}
	}

	var stepCategoryWhereStr string
	if len(stepCategoryStr) > 0 {
		stepCategoryWhereStr = fmt.Sprintf("link_id in (%s)", strings.Join(stepCategoryStr, ","))
	}

	var episodeIdWhereStr string
	if len(episodeIdStr) > 0 {
		episodeIdWhereStr = fmt.Sprintf("link_id in (%s)", strings.Join(episodeIdStr, ","))
	}

	progressData, err := P.getEpisodeTaskStepCategoryProgressData(
		nil,
		stepCategoryWhereStr,
		episodeIdWhereStr,
		req.ProjectId,
		false)
	for _, progressDataItem := range progressData {
		res = append(res, types.TotalYearMonthEpisodeTaskProgressRes{
			EpisodeId:      progressDataItem.EpisodeId,
			StepCategoryId: progressDataItem.StepCategoryId,
			Count:          progressDataItem.Count,
			CompleteCount:  progressDataItem.CompleteCount,
		})
	}

	return
}

//totalTaskNumCount 统计任务数量
func (P ProductionManage) totalYearMonthTaskNumCount(req types.TotalTaskEntityCountReq) (res []types.TotalYearMonthTaskNumCountRes, err error) {
	err = ClickHouse.DB.Model(&model.Plan{}).
		Joins("join (select task_id from task_relation_tag where project_id=? and link_module_code in ('show_step_category', 'step_category') and link_id in ?) as pr_step_category on plan.task_id = pr_step_category.task_id", req.ProjectId, req.StepCategoryId).
		Joins("join (select link_id,task_id from task_relation_tag where project_id=? and link_module_code in ('episode') and link_id in ?) as tr_episode on plan.entity_id = tr_episode.link_id", req.ProjectId, req.EpisodeId).
		Joins("join (select task_id from task_relation_tag where project_id=? and link_module_code in ('show_step_category', 'step_category')  and link_id in ?) as tr_step_category on tr_episode.task_id = tr_step_category.task_id", req.ProjectId, req.StepCategoryId).
		Where("plan.scope = 'single' and plan.type = 'step_category' and plan.project_id = ? and plan.start_time <= ? and plan.end_time>= ?", req.ProjectId, req.EndTime, req.StartTime).
		Select("toYYYYMM(toDate(plan.end_time)) AS year_month,toYear(toDate(plan.end_time)) as year,toMonth(toDate(plan.end_time)) as month, count(distinct tr_step_category.task_id) as count").
		Group("year_month,year,month").
		Find(&res).
		Error

	return
}

//totalDirectorYearMonthEpisodeTaskProgress 统计导演每月集任务进度
func (P ProductionManage) totalDirectorYearMonthEpisodeTaskProgress(userIds []int64, projectId int64, EntityIds []int64, startTime int64, endTime int64) (res []types.TotalDirectorYearMonthEpisodeTaskProgressRes, err error) {
	err = ClickHouse.DB.Model(&model.Plan{}).
		Joins("join (select task_id from task_member where partner in ?) task_member on plan.task_id = task_member.task_id", userIds).
		Joins("join (select link_id,task_id from task_relation_tag where project_id=? and link_id in ? and link_module_code in ('episode')) r_episode on plan.task_id = r_episode.task_id", projectId, EntityIds).
		Joins("join task on task.id = plan.task_id").
		Where("plan.project_id = ? and plan.type in ('meeting','review') and plan.end_time >= ? and plan.end_time <=?", projectId, startTime, endTime).
		Select("toYYYYMM(toDate(plan.end_time)) AS year_month,toYear(toDate(plan.end_time)) as year,toMonth(toDate(plan.end_time)) as month,r_episode.link_id as episode_id," +
			"count(task.id) as count,count(if(simpleJSONExtractInt(task.json, 'task_status') = 7, 1, null)) as complete_count").
		Group("year_month,year,month,episode_id").
		Find(&res).
		Error

	return
}

//totalDirectorYearMonthTaskNumCount 统计导演任务数量
func (P ProductionManage) totalDirectorYearMonthTaskNumCount(userIds []int64, projectId int64, entityIds []int64, startTime int64, endTime int64) (res []types.TotalYearMonthTaskNumCountRes, err error) {
	if len(entityIds) == 0 {
		return
	}

	err = ClickHouse.DB.Model(&model.Plan{}).
		Joins("join (select task_id from task_member where partner in ?) task_member on plan.task_id = task_member.task_id", userIds).
		Joins("join (select link_id,task_id from task_relation_tag where project_id=? and link_id in ? and link_module_code in ('episode')) r_episode on plan.task_id = r_episode.task_id", projectId, entityIds).
		Where("plan.project_id = ? and plan.type in ('meeting','review') and plan.end_time >= ? and plan.end_time <=?", projectId, startTime, endTime).
		Select("toYYYYMM(toDate(plan.end_time)) AS year_month,toYear(toDate(plan.end_time)) as year,toMonth(toDate(plan.end_time)) as month," +
			"count(distinct r_episode.task_id) as count").
		Group("year_month,year,month").
		Find(&res).
		Error
	return
}

//getMonthList 获取月份列表
func (P ProductionManage) getMonthList(startTime int64, endTime int64) (yearMonth map[int64][]int64, err error) {
	// 开始的日期 年-月
	format := "2006-01"
	startMonth := time.Unix(startTime, 0).Format(format)

	// 结束日期 年-月
	endMonth := time.Unix(endTime, 0).Format(format)

	startTimeUnix, err := time.ParseInLocation(format, startMonth, time.Local)
	if err != nil {
		// 时间解析，异常
		return
	}

	currentMonth := startTimeUnix
	endMonthUnix, err := time.ParseInLocation(format, endMonth, time.Local)
	if err != nil {
		// 时间解析，异常
		return
	}

	yearMonth = map[int64][]int64{}
	for currentMonth.Unix() <= endMonthUnix.Unix() {
		yearMonth[int64(currentMonth.Year())] = append(yearMonth[int64(currentMonth.Year())], int64(currentMonth.Month()))
		currentMonth = currentMonth.AddDate(0, 1, 0)
	}
	return
}
